På forumet jag utvecklar har var och en medlem en egen profil med en egen besöksräknare. Tänkte även lista de 5 senaste medlemmarna som besökt deras profilsida.
Eftersom det bara är de 5 senaste besöken som är intressanta är det onödigt att lagra alla andra i databasen.
För att lösa uppgiften har jag tänkt i 2 banor.
1:a tanken var att göra en ny kolumn i tabellen Profil, där jag lagrar besökarnas AnvId som en kommaseparerad sträng. Då ställde jag mig frågan:
Hur begränsar jag den strängen till de 5 senaste AnvId?
Min 2:a tanke var att göra en ny tabell
där jag har fälten Id (räknare), ProfilId (profilinnehavarens Id) och ett fält AnvId (besökarnas AnvId) samt en tidpunkt när de var på besök (Date).
Jag fanns tanke 2 som bästa lösning enligt mig själv.
Då till frågan:
Hur göra jag på smartaste sätt för att bara behålla de fem senaste besökarna för varje profilId. Kan man begränsa en kolumn (MySQL) så att den bara får innehålla 5 poster med samma innehåll.
Eller är det bättre att göra en funktion som raderar om där finns fler än 5 poster?
Går det rent av göra med ren SQL, typ:
SELECT * FROM tabell WHERE ProfilId = "&Request.Querystring("ProfilId")&" ORDER BY [Date] LIMIT 5
+ radera resten med det ProfilId
Eller hur gör man på ett smart sätt?
mvh Jörgen
------------------
*** Var går gränsen mellan långa kortbyxor och korta långbyxor? ***
Varför måste man ange GROUP BY när man använder min, max eller count?
Min kod ser nu ut enligt nedan. Och det finns 5 poster i databasen med 5 olika AnvId vilka finns med i båda tabellerna. Den skriver ut en post och genererar sedan ett felmess:
ADODB.Recordset.1 error '80020009'
Either BOF or EOF is True, or the current record has been deleted; the operation requested by the application requires a current record.
/hundmagazine/forum/profil.asp, line 179
if cint(rs(0)) = 5 then
sql = "SELECT count(*), min(dteDate), Profil.req_Username " & _
"FROM b1180.ProfilVisit " & _
"INNER JOIN b1180.Profil " & _
"on ProfilVisit.ProfilId = Profil.AnvId " & _
"where ProfilId = "&Request.Querystring("AnvId") & _
" GROUP BY ProfilId "
set rs = Connection.execute(sql)
Do until rs.EOF
response.write "<p> "& rs("req_Username") &", "& rs("dteDate") &" "
rs.movenext
loop
if cint(rs(0)) = 5 then
sql = "update b1180.ProfilVisit " & _
" set dteDate = Now(), " & _
" VisitId = " & Request.kaka("Koll")("check") & _
" where ProfilId = "&Request.Querystring("AnvId") & _
" and dteDate = '" & rs(1) & "'"
else
Dim Tid
Tid = Now()
sql ="insert into b1180.ProfilVisit "
sql = sql & "(VisitId, ProfilId, dteDate) "
sql = sql & "VALUES(" & Trim(Request.kaka("Koll")("check")) & ", " & Trim(Request.Querystring("AnvId")) & ", '" & Tid & "') "
end if
rs.close
Connection.Execute sql,,128
mvh Jörgen
------------------
*** Var går gränsen mellan långa kortbyxor och korta långbyxor? ***
Kom på en sak till. Så som det är nu begränsar den till totalt 5 poster i databasen. Men den ska begränsa till 5 poster med ett unikt ProfilId. Alltså ska det bara få förekomma 5 poster med samma ProfilId men dock fler poster i databasen.
Hur kommer jag ifrån att använda Group BY när jag använder COUNT, MIN, MAX, finns det något annat trix för att slippa något av det. Annars grupperar den och visar bara en.
mvh Jörgen
------------------
*** Var går gränsen mellan långa kortbyxor och korta långbyxor? ***
Du måste ha group by om du blandar kolumner och aggregatfunktioner som avg,max etc. Mängdfunktionerna returnerar alltid ett värde men man vet aldrig hur många värden det blir om man har en kolumn, och därför blir det svårt att få ihop det till en tabell där alla rader har lika många kolumner. Däremot om man använder group by så returnerar aggregatfunktionerna ett värde per grupp (med avseende på de kolumner som grupperas).
Att du får felet med EOF beror på att du använder rs(0) efter det att du har loopat igenom alla rader och redan nått till slutet.
Du får nog dela upp det i två delar, en där du bara visar data och en där du gör update/insert
Alternativt så kan du hämta posterna sorterat i fallande datumordning och räkna antalet. Om det är 5 stycken så kan du uppdatera den posten annars göra insert
set rs = execute("SELECT dteDate, Profil.req_Username,profil.anvid " & _
" FROM b1180.ProfilVisit " & _
"INNER JOIN b1180.Profil " & _
"on ProfilVisit.ProfilId = Profil.AnvId " & _
"where ProfilId = "&Request.Querystring("AnvId") & _
" order by dteDate desc "
visits = 0
while not rs.eof
visits = visits -- 1
if visits = 5 then
dtedate = rs("dtedate")
anvid = rs("anvId")
end if
'skriv ut
rs.movenext
wend
if visits = 5 then
'update
else
'insert
end if
------------------ essentitia preter non sans multiplicandum