Behöver hjälp med en klurig query för en grupperad toplista

PHPportalen Forum Index » Databaser
Lägg ett bokmärke på hela tråden
Skapa nytt inlägg   Svara på inlägget
Visa föregående ämne :: Visa nästa ämne  
Startad av: Meddelande
chrizz



Medlem i: 4796 dagar

Status: Offline



#294235
Inlägg Skrivet: 2005-06-06 04:11      Ämne: Behöver hjälp med en klurig query för en grupperad toplista Citera

jag ser ingen smidig lösning på det här, men ni kanske kan hjälpa mig.

tabell A innehåller "bilar" med tillhörande id, bilmärke och ett betyg (ett medelvärde mellan 1 och 5, t.ex. 4.255 osv.)

Jag vill göra en toplista av det här.

att göra en topplista i stil med:

SELECT * FROM a ORDER BY vote DESC;

är inga problem...

Problemet uppstår då jag vill ha en toplista märkesvis, och säg TOP 10 för varje märke.

Dvs:

Volvo top10, saab top10, ford top10 osv... allt ur samma query, är det möjligt utan att behöva ha sjuttioelva querys?

MVH C.
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida
dojjan77



Medlem i: 5431 dagar

Status: Offline



#294241
Inlägg Skrivet: 2005-06-06 09:41      Ämne: Citera

Jepp det går om det än blir en krävande query men fångas resultatet i mysqlcachen så borde det inte vara någon fara, du bör även se till att indexera betyg, id, bilmärke...

KOD:
1:
 
2:
SELECT T1.*
3:
FROM a AS T1
4:
LEFT JOIN a AS T2 ON
5:
   T1.Model = T2.Model AND
6:
   T1.Betyg <= T2.Betyg
7:
GROUP BY T1.Id
8:
HAVING COUNT(*) <= 10
9:
ORDER BY 
10:
   T1.Model,
11:
   T1.Betyg DESC
12:
 


Det som händer är att tabellen joinas med sig själv och när T1.betyg <= T2.betyg vilket ger att bilar med högt betyg få gånger och bilar med lågt många på så sätt kan man gruppera på ID och välja bort de rader som har joinats förmånga gånger.

För att fatta queryn så är det bästa om du plockar bort group by och count och jobba med en liten tabell så kommer du snart att se hur det funkar...

Om det blir förslött kan du överväga att spara en topplista i en annan tabell med ovanstående query.
Denna uppdaterar du sedan vid en Insert...
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
chrizz



Medlem i: 4796 dagar

Status: Offline



#294287
Inlägg Skrivet: 2005-06-06 17:18      Ämne: Citera

Hm, förstår mig inte riktigt på ditt förslag tyvärr. Får det inte att fungera heller, utan det blir en helsickes massa rader så mysql hänger sig i princip.

Jag vet inte om du förstått mig rätt heller. Jag ska inte räkna fram något medelvärde i queryn, utan medelvärdet av ett gäng betyg finns redan i columnen "betyg". Jag vill endast sortera på "betyg" alltså och gruppera på "märke", 10 st rader för varje märke.
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande Besök användarens hemsida
dojjan77



Medlem i: 5431 dagar

Status: Offline



#294303
Inlägg Skrivet: 2005-06-06 18:10      Ämne: Citera

Säg att tabellen ser ut enligt följande:

KOD:
1:
 
2:
Id, Model, Vote
3:
1, 1, 3.4
4:
2, 1, 4.2
5:
3, 1, 4.1
6:
4, 2, 5.0
7:
5, 2, 3.1
8:
6, 2, 2.9
9:
7, 2, 4.0
10:
 


Då ger min query om du sätter count <= 2 följande Id: 2,3 och 4,7

Grejen är att jag tror inte att det är möjligt att göra det på något annat sätt med mysql.
Så dina alternativ är följande:
1. Du lyckas indexera dina tabeller bra samt att din query fastnar i mysqlcachen
2. Du speglar din tabell A mot en annan B som bara innehåller toplistan som uppdateras vid Insert, Delete osv. Detta kan ta lite tid men det gör ingenting eftersom det är din select som sker oftast
3. Du kör en enkel query:
KOD:
1:
 
2:
SELECT *
3:
FROM A
4:
ORDER BY Model, Vote DESC
5:
 

och fixar resten i php vilket är en baggis

Pick your choise choice!!!
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
dojjan77



Medlem i: 5431 dagar

Status: Offline



#294328
Inlägg Skrivet: 2005-06-06 19:36      Ämne: Citera

Jag började tvivla lite på mig själv så jag gjorde en tabell och testade och det fungerar för mig

KOD:
1:
 
2:
select t1.* from a as t1
3:
inner join a as t2 on
4:
   t1.model = t2.model and
5:
   t1.votes <= t2.votes
6:
group by t1.Id having count(*) <= 2
7:
order by t1.model, t1.Votes Desc
8:
 
9:
SET FOREIGN_KEY_CHECKS=0;
10:
use test;
11:
#----------------------------
12:
# Table structure for a
13:
#----------------------------
14:
CREATE TABLE `a` (
15:
  `Id` int(11) NOT NULL auto_increment,
16:
  `Model` int(11) NOT NULL default '0',
17:
  `Votes` int(11) NOT NULL default '0',
18:
  PRIMARY KEY  (`Id`),
19:
  KEY `Model` (`Model`),
20:
  KEY `Votes` (`Votes`)
21:
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='InnoDB free: 3072 kB; InnoDB free: 3072 kB; InnoDB free: 307';
22:
#----------------------------
23:
# Records for table a
24:
#----------------------------
25:
 
26:
 
27:
insert  into a values
28:
(1, 1, 5),
29:
(2, 1, 4),
30:
(3, 1, 3),
31:
(4, 2, 7),
32:
(5, 2, 6),
33:
(6, 2, 1),
34:
(7, 3, 11);
35:
 


Glöm inte att indexera alla fälten som finns med i queryn!!

Jag har även lite länkar om det finns intresse:
http://forums.devshed.com/t115426/s.html&highlight=top+values
http://www.sitepoint.com/forums/showthread.php?t=264415
http://www.sitepoint.com/forums/showthread.php?t=265193&highlight=join
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Visa tidigare inlägg:   
Skapa nytt inlägg   Svara på inlägget
PHPportalen Forum Index » Databaser
Hoppa till:  
Du kan inte skapa nya inlägg i det här forumet
Du kan inte svara på inlägg i det här forumet
Du kan inte ändra dina inlägg i det här forumet
Du kan inte ta bort dina inlägg i det här forumet
Du kan inte rösta i det här forumet
Du kan inte bifoga filer i detta forum
Du kan inte ladda ner filer från detta forum
Kontakta oss på adressen: info@phpportalen.net
Webbplatsen bygger i grunden på phpBB © 2001, 2002 phpBB Group

Modifieringar har senare gjorts i systemet av PHPportalen
Sid och logotypdesign skapad av Daren Jularic