Avatar billede Slettet bruger
08. august 2011 - 13:24 Der er 9 kommentarer og
1 løsning

Løkke i et sql med funktionen exists, som ikke virker

campaignsSplitted = split(campaigns, ", ")
sql = "select count(*) as total from kampagner"

for i = 0 to ubound(campaignsSplitted)
  if i = 0 then
    sql = sql & " (where id = " & campaignsSplitted(i)
  else
    sql = sql & " or id = " & campaignsSplitted(i)
  end if
next

sql = sql & ") and exists(select campaign from rapporter where kampagner.id = rapporter.campaign)"

set rs = conn.execute(sql)

usersCount = usersCount + (rs("total") * 3)


Pointen er, at campaignsSplitted er af en variabel størrelse, alt afhængig af hvad der er gemt i databasen. Den skal finde alle rækker i tabellen kampagner hvor id er lig de id i campaignsSplitted-arrayet, men KUN hvis der samtidigt findes en række i tabellen rapporter hvor kolonnen campaign er lig id'et fra campaignsSplitted.

Det som sker her er, at exists-funktionen åbenbart ALTID er true, af en eller anden mærkelig grund :/

Nogen der kan hjælpe og evt. optimere?
Avatar billede softspot Forsker
08. august 2011 - 13:45 #1
Prøv evt. denne:

sql = "select count(*) as total " & _
      "from kampagner " & _
      "where id in (" & campaigns & ") " & _
      "and (" & _
        "select count(*) " & _
        "from rapporter " & _
        "where campaign = kampagner.id" & _
      ") > 0"
set rs = conn.execute(sql)
usersCount = usersCount + (rs("total") * 3)

Der er dog en risiko for SQL-injections via campaigns-variablen, med mindre du er 100% sikker på at det er en kommasepareret liste med gyldige id'er... det er dog ikke anderledes end udgangspunktet.
Avatar billede Slettet bruger
08. august 2011 - 14:21 #2
Tæller den der ikke også alle rækkerne i tabellen rapporter med?
Dvs, de OGSÅ bliver usersCount = usersCount + (rs("total") * 3)?

Meningen er nemlig, at den kun skal tælle 3 i tabellen kampagner imens tabellen rapporter bliver talt efterfølgende, men kun tæller 1 :)
Avatar billede softspot Forsker
08. august 2011 - 14:41 #3
Næh, den subquery i where-delen af hoved sql-sætningen, burde blot undersøge om der findes mindst én række i rapporter med det aktuelle kampagneid. Jeg er dog en smule usikker på om den nøglereference mellem kampagner og rapporter fungerer, når man foretager en optælling...

Alternativt skal du joine de to tabeller og så kun tælle de rækker der har mindst én relateret række i rapporter. Noget i stil med dette (lidt pseudokodeagtigt):

select count(*) as total
from (
  select k.id, count(*)
  from kampagner k
  inner join rapporter r on r.campaign = k.id
  where id in (<campaigns-variablen indsættes her>)
  group by k.id
)
Avatar billede Slettet bruger
08. august 2011 - 15:00 #4
Det kan meget muligt virke.
Jeg kigger lige på forslaget i aften når jeg kommer hjem og ser hvordan det passer ind:)
Avatar billede Slettet bruger
10. august 2011 - 16:12 #5
Hej softspot, så fik jeg langt om længe tid til at kigge på den, og jeg har nu siddet og leget lidt med det.

Jeg kan dog ikke få det helt til at virke, da jeg får en fejl jeg bare ikke kan finde.

Jeg har følgende kode:

"select count(*) as total from (select k.id, count(*) from intra_campaigns k inner join intra_rapports r on r.campaign = k.id where id in (60, 47, 59, 58, 41, 48) group by k.id)"
set rscount = conn.execute(sqlcount)
usersCount = usersCount + (rscount("total") * 3)


Men får fejlen:
Microsoft OLE DB Provider for SQL Server fejl '80040e14'

Incorrect syntax near ')'.

/intra/bigscreens.asp, linje 503

Og linie 503 er selvfølgelig SQL linien.
Avatar billede Slettet bruger
10. august 2011 - 16:12 #6
Der er selvfølgelig en sqlcount = foran sql sætningen :)
Avatar billede softspot Forsker
10. august 2011 - 16:51 #7
Prøv evt. med denne SQL:

sqlcount = "select count(*) as total " & _
    "from (" & _
        "select k.id, count(*) " & _
        "from intra_campaigns k " & _
        "inner join intra_rapports r " & _
            "on r.campaign = k.id " & _
        "where k.id in (60, 47, 59, 58, 41, 48) " & _
        "group by k.id" & _
    ") as tmp"

Jeg kan ikke umiddelbart se nogen fejl, men det kan være man skal tildele subquery'en et alias (det mener jeg man skal på SQL Server). Desuden har jeg præfikset id i subquery'ens where-sætning for at undgå evt. dobbelttydigheder mht. hvilken tabel id'et kommer fra af de to der joines...

Alternativt må man ikke gruppere i en subquery. I så fald kan du prøve at ændre sætningen til:

sqlcount = "select count(*) as total " & _
    "from (" & _
        "select top 100 percent k.id, count(*) " & _
        "from intra_campaigns k " & _
        "inner join intra_rapports r " & _
            "on r.campaign = k.id " & _
        "where k.id in (60, 47, 59, 58, 41, 48) " & _
        "group by k.id" & _
    ") as tmp"

eller måske til:

sqlcount = "select count(*) as total " & _
    "from (" & _
        "select distinct k.id " & _
        "from intra_campaigns k " & _
        "inner join intra_rapports r " & _
            "on r.campaign = k.id " & _
        "where k.id in (60, 47, 59, 58, 41, 48)" & _
    ") as tmp"

Bemærk at jeg i den sidste version har fjernet grupperingen fra subquery'en.
Avatar billede Slettet bruger
10. august 2011 - 18:47 #8
Jeg har prøvet alle 3 forslag.

Sætter jeg as tmp på får jeg følgende:
Microsoft OLE DB Provider for SQL Server fejl '80040e14'

No column name was specified for column 2 of 'tmp'.

/intra/bigscreens.asp, linje 503

Sættes den ikke på, får jeg samme fejl som før.
Avatar billede Slettet bruger
16. august 2011 - 16:53 #9
Slet ingen ? :/
Avatar billede Slettet bruger
26. september 2011 - 21:26 #10
Jeg lukker, fandt et alternativ til det hele
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester