webForumDet fria alternativet

Group by och order by ....

Databaser & SQLur Databashanterare & SQL

6 svar · 259 visningar · startad av D-M_R

Medlem sedan aug. 2002114 inlägg
Frågan#1

Så här äre. Forum. Jag vill lista alla användare som har varit aktiva under X senaste minutrarna. För detta har jag en kolumn som heter "usr_lastAction". Så vill jag också länka till användarens senaste inlägg. Men jag vill inte först hämta ut alla användare som vart aktiva, loopa dem och hämta deras senaste inlägg i loopen. För det blir en massa querys som jag inte vill köra. Nej nej. Jag vill hämta ut allt på en gång.

Jag kom så långt så jag fick listat Användarnamnet - Inläggets id - Topicets Id. För alla användare som varit aktiva. Bara ett problem. Den listar ALLA användarens inlägg. Så om Björn var aktiv under senaste X minuter och skrivit totalt 5 inlägg under forumets livstid samtidigt som Nisse va aktiv och hade postat 3 inlägg under hela sin livstid så blev det så här

Björn - 24 - 1
Björn - 23 - 1
Björn - 20 - 1
Björn - 15 - 1
Björn - 10 - 1
Nisse - 8 - 1
Nisse - 5 - 1
Nisse - 3 - 1

När jag egentligen bara vill lista

Björn - 24 - 1
Nisse - 8 - 1

Eftersom de andra raderna är ointressanta.

Jag tänkte ... Hur ska ja göra detta. Ja vet. GROUP BY. Så ja la in en GROUP BY usr_id ... Blev ju nästan rätt. Istället för att lista.

Björn - 24 - 1
Nisse - 8 - 1

Så listade den

Björn - 10 - 1
Nisse - 3 - 1

Som alltså är aktiva användarna och deras FÖRSTA post istället för deras SISTA post.

Den listade så här OAVSETT hur min ORDER BY såg ut ...

Så här ser SQL ut när jag listar användaren UTAN group.

$sql = "SELECT * FROM unity_users, forum_posts WHERE usr_lastAction > ".(time()-(60*30))." AND unity_users.usr_id = forum_posts.usr_id ORDER BY usr_lastAction DESC, forum_posts.fp_regTime";

Då får jag som första exemplet.
Och när jag har group by med.

$sql = "SELECT * FROM unity_users, forum_posts WHERE usr_lastAction > ".(time()-(60*30))." AND unity_users.usr_id = forum_posts.usr_id GROUP BY unity_users.usr_id ORDER BY usr_lastAction DESC, forum_posts.fp_regTime";

Då får jag som sista exemplet.

Någon som har något förslag?

Medlem sedan feb. 20001 861 inlägg
#2

Kan du inte skippa GROUP BY och lägga till LIMIT 1 istället?

Medlem sedan aug. 2002114 inlägg
#3

Limit 1 så hämtar ju den bara en post. Ja ska ju hämta alla användare som är aktiva ... Kör jag Limit 1 så hämtar den ju bara första raden oavsett ....

Medlem sedan dec. 200012 464 inlägg
#4

Normalt så skulle man lösa detta med en korrelerad subselect men det finns inte i Mysql.

Det kanske går att tricka till det

$sql = "SELECT unity_users.userid,
max(concat(lpad(postid,11,'0'),lpad(topicid,11,'0'))) as  potid  
FROM unity_users, forum_posts 
WHERE usr_lastAction > ".(time()-(60*30))." 
AND unity_users.usr_id = forum_posts.usr_id 
GROUP BY unity_users.usr_id 
ORDER BY usr_lastAction DESC, forum_posts.fp_regTime";

då får du dela potid och ta bort de inledande nollorna i php.

Det sätt som du använder group by på är egentligen helt felaktigt, det är bara Mysql som tillåter det. I alla andra dbms så måste alla kolumner i select-listan som inte ingår i group vara ett argument till en aggregeringsfunction (max,min etc).

Medlem sedan aug. 2002114 inlägg
#5

mkaj ... man lär sig något nytt varje dag :)
massa nollor blir det. är det alltid lika många jag ska ta bort?
eller skapar den olika många? ... så man inte råkar göra post_id 1990 till 199 å sådant :)

Medlem sedan aug. 2002114 inlägg
#6

fatta va den gjorde nu. så de löser sig :)
ja är lite trög ibland

STORT tack iaf!! :)

Medlem sedan feb. 20001 861 inlägg
#7

Tänkte lite fel, sorry!

131 ms totalt · 3 externa anrop · v20260731065814-full.4bcf49fe
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
128 ms — hämta tråd, inlägg och bilagor (db)