Toon posts:

[SQL/MYSQL] Laatste x berichten per type (opgegeven of niet)

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ben al heel de dag aan het kloten om een listing van de laatste berichten per type te maken.

stel je hebt tabel cms_content:
CmsContentIdCmsContentTitleCmsContentBodyCmsContentDatetimeCmsContentType
1nieuws 1eerste nieuws2005-08-31 22:06:101
2nieuws 2tweede nieuws2005-08-31 22:06:431
3product 1eerste product2005-08-31 22:07:232
4nieuws 3derde nieuws2005-08-31 22:09:551
5product 2tweede product2005-08-31 22:10:132
6product 3derde product2005-08-31 22:10:492


Nu kun je natuurlijk doen:
code:
1
2
3
4
5
SELECT *
FROM cms_content
WHERE CmsContentType = 1
ORDER BY CmsContentDatetime DESC
LIMIT 0 , 2


Dit werkt prima voor één enkel type. Maar ik wil de laatste twee berichten per (opgegeven) type. Aangezien subqueries al werken (versie 4.1 dacht ik) probeer ik:
code:
1
2
3
4
5
6
7
8
9
10
11
SELECT *
FROM `cms_content`
WHERE `CmsContentId`
IN (

SELECT `CmsContentId`
FROM cms_content
WHERE `CmsContentType` =1
ORDER BY `CmsContentDatetime` DESC
)
ORDER BY `CmsContentType` , `CmsContentDatetime` DESC


Dit is dus uit te breiden door meerderen IN()'s te gebruiken.

Dit werkt, nu ff de limit erin en klaar:
code:
1
2
3
4
5
6
7
8
9
10
11
12
SELECT *
FROM `cms_content`
WHERE `CmsContentId`
IN (

SELECT `CmsContentId`
FROM cms_content
WHERE `CmsContentType` =1
ORDER BY `CmsContentDatetime` DESC
LIMIT 0 , 2
)
ORDER BY `CmsContentType` , `CmsContentDatetime` DESC


Probleem
Dit werkt dus niet in deze versie van MySql (MySQL 4.1.10a-nt). Ik krijg de melding:
code:
1
2
 MySQL retourneerde: Documentatie
#1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'


Oftewel die truc gaat niet op. Nu heb ik echter geen enkel idee hoe ik dit wel kan oplossen. Iemand een idee?

ter info
MySQL 4.1.10a-nt
Examples van MySql: http://dev.mysql.com/doc/mysql/en/examples.html bieden geen uitkomt.

[ Voor 6% gewijzigd door Verwijderd op 31-08-2005 23:49 ]


Verwijderd

2 oplossingen:
1) 1 query draaien zonder LIMIT en dan tijdens het uitlezen filteren. Nadeel is dat de belasting erg groot is met veel records
2) Doe 1 query per type en voeg deze met een UNION samen.

HTH :)

Verwijderd

Topicstarter
Mooi dat UNION ook geimplementeerd is :-) Niet eens meer aan gedacht, omdat dit in 3 niet kon... Bedankt!

Net UNION getest, maar dit blijkt alleen erg traag!
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$objSw  = new clsStopwatchControl();
mysql_connect('localhost','root');
mysql_select_db('cms');
$objSw->doStart();

$iTest = 100;

for ($x=0;$x<$iTest;$x++)
{
mysql_query('SELECT * FROM cms_content WHERE CmsContentType = 1');
mysql_query('SELECT * FROM cms_content WHERE CmsContentType = 2');
}
echo $objSw->doStop();
echo '<br>';
$objSw->doStart();
for ($x=0;$x<$iTest;$x++)
{
mysql_query('(SELECT * FROM cms_content WHERE CmsContentType = 1) UNION (SELECT * FROM cms_content WHERE CmsContentType = 2)');
}
echo $objSw->doStop();


Dit geeft als uitkomt:
code:
1
2
0.037209
0.883842


clsCtopwatch is een timer klasse die het verschil in seconden print.

Nu blijkt wel uit de test dat twee keer een losse querie veel sneller is.

Is er geen snellere manier dan dit?
Komt dit doordat MySql achterliggend een Temp tabel aanmaakt?

[ Voor 89% gewijzigd door Verwijderd op 01-09-2005 16:19 . Reden: Aangezien een nieuwe reply een kick oplevert een edit. ]


  • sig69
  • Registratie: Mei 2002
  • Laatst online: 18:45
Hoeveel records staan er in je tabel?
Ik kan geen php meer maar als ik het zo zie duurt het uitvoeren van 100x de query met UNION 0.883842 seconden, dat is 0.00883842 seconde per query. Wellicht dat er met indexen en een beetje tuning nog meer uit te halen valt.

Roomba E5 te koop


Verwijderd

Ik vermoed dat MySQL inderdaad een temp tabel aan zal maken met gebruik van UNION. Soms kan je dan beter meerdere eenvoudige queries doen en die met code tot een zinvol resultaat breien, en dit lijkt me zo'n typisch geval daarvoor.

Verwijderd

Topicstarter
sig69 schreef op vrijdag 02 september 2005 @ 09:19:
Hoeveel records staan er in je tabel?
Ik kan geen php meer maar als ik het zo zie duurt het uitvoeren van 100x de query met UNION 0.883842 seconden, dat is 0.00883842 seconde per query. Wellicht dat er met indexen en een beetje tuning nog meer uit te halen valt.
Er is een index aangemaakt op de CmsContentType tabel. Mogelijk zijn deze resultaten zonder index gemaakt, echter een verschil met een index levert geen noemenswaardig verschil op, er zaten toen ook maar 6 records in deze tabel. Ook heb ik er naderhand nog wat fake data ingegooid, met index. Ook dit leverde dezelfde tijden op.

Het worden dus (voorlopig) losse queries. Hopelijk wordt het gebruik van een subquerie met limit snel geimplementeerd.
Pagina: 1