Avatar billede nightowl24 Nybegynder
09. januar 2007 - 16:05 Der er 11 kommentarer og
1 løsning

Optimering af ASP script

Jeg skal have udviklet et ASP script der skal kunne udskrive et skema
over hvor mange besøgende der har været pr. sommerhus i et idrætscenter.

Hver sommerhus har selfølgelig en nøgle og på den er der et nummer.

Hver gang der kommer besøgende i idrætscenteret viser de nøglen(hvis de er fra et sommerhus)
og det registreres hvor mange de er.

Derfor har jeg lavet en tabel i access med følgende felter:

KeyCode | antal | dato

Listen der udskrives skal se ud som følgende:

nøglenr./dato | 1 | 2 | 3 | 4 | 5 ...
dk01
dk02
dk03
...
...

For hver nøgle skal jeg altså tjekke hvor mange antal der er for hver dato:

Det ser således ud i mit script:

response.write "<table id=""besoegsliste-table"" cellpadding=""2"" cellspacing=""1""><tr><td class=""besoegsliste-td"" style=""width: 100px;"">Husnr.:</td>"
FOR i=1 TO sidsteDagiMaaned
response.write "<td class=""besoegsliste-td"">"&i&"</td>"
NEXT
response.write "</tr>
WHILE NOT objRS.EOF
SamletAntal = 0
response.write "<tr><td class=""besoegsliste-td""><b>"&objRS("KeyCode")&"</b></td>"
FOR i=1 TO sidsteDagiMaaned 
  dato = i&"-"&Maaned&"-"&currentYear
  sql = "SELECT sum(antal) as antal FROM keyStats WHERE dato = #"&convertDate(dato)&"# AND keyCode = '"&objRS("KeyCode")&"'"
  objRSA.open sql, objConn
response.write "<td class=""besoegsliste-td"">" &objRSA("antal")& "</td>"
IF not isNull(objRSA("antal")) THEN
  SamletAntal = SamletAntal + objRSA("antal")
END IF
objRSA.close
NEXT
response.write "<td class=""besoegsliste-td"">" & SamletAntal & "</td>"
objRS.moveNext
response.write "</tr>"
wend
response.write "</table>"

Dette script virker, men det går ufattelig langsomt, fordi der er så mange kald til databasen.

Er der nogen der har en god idé til hvordan dette kan optimeres?
Avatar billede fennec Nybegynder
09. januar 2007 - 16:24 #1
Du burde kunne trække det hele ud med en select:

"select keyCode, dato, sum(antal) as antal from keyStats group by keyCode, dato, order by keyCode, dato"
Avatar billede fennec Nybegynder
09. januar 2007 - 16:33 #2
Du skal godt nok selv styre en del af visningen, da alle kommer ud i selvstændige rækker, og de kan evt godt springe i datoerne. Det kan godt være lidt indviklet at klare...

Det er noget mad at styre oldKey og sammenligne med den nuværende record, og se om der er forskeld, og i givetfald lave en ny række i tabellen.

Datoerne skal så løbes igennem samtidig med at man flytter til næste record, hvis man finder en match.

Det er meget svært at forklare.
Avatar billede fennec Nybegynder
09. januar 2007 - 16:40 #3
Mangler da lige en dato begrænsning på selecten:

sql = "select keyCode, dato, sum(antal) as antal from keyStats where dato between #01-01-2007# and #01-31-2007# group by keyCode, dato, order by keyCode, dato"

Access bruger´desuden mm-dd-yyyy formatet, så måneden skal stå først.
Avatar billede nightowl24 Nybegynder
10. januar 2007 - 09:35 #4
Tror jeg er på rette spor nu, men har følgende problem:

Jeg har 2 tabeller

Keys, som indeholder alle nøgler i systemet.
Felterne er:
KeyID, KeyCode, Aar, maxAntal, BureauID

KeyStats, som indeholder de nøgler der er registreret et besøg på.
Felterne er:
KeyStatsautoID
KeyCode
antal
dato

Det jeg skal have ud, er en liste over alle nøgler fra et bestemt bureau, fra
01-01-07 til 31-01-07, samt antal besøgende pr. dag.

Nøgle | dato | antal
-
-
-


Hvordan gør jeg dette? Jeg kan kun få de nøgler ud hvor der er registreret et antal besøgende.

Min sqlsætning indtil videre:

SELECT Keys.KeyCode, dato, sum(antal) as antal FROM keyStats, Keys WHERE dato between #"&start_dato&"# AND #"&slut_dato&"# AND Keys.Keycode = KeyStats.KeyCode AND Keys.bureauID = "&objRSb("bureauID")&" GROUP BY Keys.KeyCode, dato ORDER BY Keys.KeyCode, dato
Avatar billede fennec Nybegynder
10. januar 2007 - 09:55 #5
Lav et "rigtig" join, så kan du godt få data ud. Det gøres nemlig med et left join:

SELECT Keys.KeyCode, dato, sum(antal) as antal FROM Keys left join keyStats on Keys.Keycode = KeyStats.KeyCode WHERE dato between #"&start_dato&"# AND #"&slut_dato&"# AND Keys.bureauID = "&objRSb("bureauID")&" GROUP BY Keys.KeyCode, dato ORDER BY Keys.KeyCode, dato

Normale join hedder "inner join". Left join gør at man sikre at alle rækker fra en tabel kommer med selv om de ikke har referencer i den anden tabel.
Avatar billede fennec Nybegynder
10. januar 2007 - 09:58 #6
Der er vist en rettelse til, da du siger at dato skal være mellem nogle værdier, så mister left join sin egenskab. Det kan klares med en lille or betingelse.

... WHERE ((dato between #"&start_dato&"# AND #"&slut_dato&"#) OR dato is NULL) and ...
Avatar billede nightowl24 Nybegynder
10. januar 2007 - 10:07 #7
Rigtig godt, så må jeg se om jeg kan lave et skema ud fra dette.
Avatar billede fennec Nybegynder
10. januar 2007 - 10:51 #8
Ellers kan du også lave lave den knap så indviklet, men med lidt flere select:

set rs1 = conn.execute("select * from Keys")
while not rs1.eof
  set rs2 = conn.execute("select * from keyStats where dato between #"&start_dato&"# AND #"&slut_dato&"# order by dato")
  for f=1 to sidsteDagiMaaned
    ... Noget kode ...
  next
  rs1.MoveNext
wend

Som du kan se får du så AntalKeys+1 antal selects, mod den anden som kun har en. Afhængig af server/database/programør er den ene løsning bedre end den anden.

1: Med 1 select får du indviklet kode, som kan være svær at tyde for andre, samt den fylder mere og tager derfor længere tid at køre.

2: Med multiselect er koden mere simpel og koden kører hurtigere, men der tabes tid på database selects.
Avatar billede fennec Nybegynder
10. januar 2007 - 10:52 #9
Der manglede lige en betingelse mere på rs2:

set rs2 = conn.execute("select * from keyStats where dato between #"&start_dato&"# AND #"&slut_dato&"# and keycode="& rs1("keycode") &" order by dato")
Avatar billede nightowl24 Nybegynder
10. januar 2007 - 11:51 #10
Jeg har fået det til at spille med følgende den ene sql:

WHILE NOT objRS.EOF ' Gennemløb af nøgler
  IF lastKey <> "" THEN ' forrige nøgle eksistere, tmpArray eksistere
   
    IF lastKey = objRS("keyCode") THEN ' Hvis aktuelle nøgle er lig sidst tjekkede nøgle
   
    IF not isNull(objRS("dato")) THEN
      myDato = SPLIT(objRS("dato"), "-") 'Kan muligvis ikke afvikles
      currentDay = myDato(0)
      tmpArray(currentDay) = objRS("antal")
    END IF   
    lastKey = objRS("KeyCode")
   
    ELSE
    response.write "<tr><td class=""besoegsliste-td"">"&replace(lastKey, " ", "nbsp;")&"</td>"
    FOR i=1 to sidsteDagIMaaned
      IF tmpArray(i) <> "" THEN
      response.write "<td class=""besoegsliste-td"">"&tmpArray(i)&"</td>"
      ELSE
      response.write "<td class=""besoegsliste-td""></td>"
      END IF
    NEXT
      response.write "</tr>"   
      REDIM tmpArray(sidsteDagIMaaned) 'array tømmes
      IF not isNull(objRS("dato")) THEN
      myDato = SPLIT(objRS("dato"), "-") 'Kan muligvis ikke afvikles
      currentDay = myDato(0)
      tmpArray(currentDay) = objRS("antal")
      END IF   
      lastKey = objRS("KeyCode")
    END IF
   
  ELSE    ' Der eksistere ingen forrig nøgle, tmpArray oprettes
       
    REDIM tmpArray(sidsteDagIMaaned)
    IF not isNull(objRS("dato")) THEN
    myDato = SPLIT(objRS("dato"), "-") 'Kan muligvis ikke afvikles
    currentDay = myDato(0)
    tmpArray(currentDay) = objRS("antal")
    END IF   
    lastKey = objRS("KeyCode")
  END IF
  objRS.moveNext
  Wend
  response.write "</table></div>" 
 
  objRSb.moveNext
  objRS.close
  wend
Avatar billede nightowl24 Nybegynder
10. januar 2007 - 11:51 #11
Og du må meget gerne smide et svar
Avatar billede fennec Nybegynder
10. januar 2007 - 12:32 #12
.o) <-- One Eyed Jack
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