Autor Zpráva
llook
Profil
Na SQL jsem asi levej. Mám tabulku verzí stránek a chtěl bych vybrat nejnovější verzi od každé stránky.

Tabulka vypadá nějak takhle:
CREATE TABLE `versions` (

-- tady jsou nějaká pro teď nedůležitá pole

`created` DATETIME,
`page_id` INT
);


Když vyberu všechno GROUP BY `page_id`, tak sice mám od každé stránky jen jednu verzi, ale ne nejnovější. Potřeboval bych, aby se data před seskupením seřadila.

Myslel jsem, že by to mělo jít nějak takhle, ale nejde:
SELECT *, MAX(`created`) as 'max_created' FROM `versions` GROUP BY `page_id` HAVING `created`=`max_created`;
(Vybere to jenom jednu, tu úplně nejnovější a to je mi na nic.)

Věděl bych jak to udělat poddotazem, ale nechci se kvůli tomu odstřihnout od MySQL 4.0.x. Nějaký nápad?
Anonymní
Profil *
GROUP BY `page_id`DESC LIMIT 1
Kajman
Profil *
Zkus to takhle nějak...

SELECT p.*, MAX(`o.created`) AS 'max_created' FROM `versions`AS o LEFT JOIN `versions` AS p ON `p.idcl`=`o.idcl` GROUP BY `p.page_id`, `p.created` HAVING `p.created`=`max_created`;
llook
Profil
Kajman Díky, ale nějak se mi to nedaří zprovoznit. Zatím jediné čistě SQL řešení na které jsem přišel je přes dočasnou tabulku:
CREATE TEMPORARY TABLE `tmp_versions_count` (`created` DATETIME);

INSERT INTO `tmp_versions_count` SELECT MAX(`created`) as 'created' FROM `versions` GROUP BY `page_id`;
SELECT * FROM `versions` JOIN `tmp_versions_count` USING(`created`);
Anonymní
Profil *
v podstate si to mel dobre jen tam mas navic to having

ma to byt takhle

SELECT *, MAX(created) FROM versions GROUP BY page_id ;
kaifman
Profil
to sem byl ja :)
llook
Profil
To právě ne. Tím získám všechna pole prvního záznamu ve skupině (*) plus hodnotu nejvyššího created v tý skupině (max(created)). Vrátí to například tohle:
+----+---------------------+---------+---------------------+

| id | created | page_id | max(created) |
+----+---------------------+---------+---------------------+
| 1 | 2005-10-09 04:23:28 | 1 | 2005-10-09 05:16:42 |
| 5 | 2005-10-09 05:16:35 | 2 | 2005-10-09 05:17:14 |
+----+---------------------+---------+---------------------+

Mnou požadovaný stav je ten, že created=max(created)
Kajman
Profil *
Tak to je divné, že to nešlo, myslel, jsem že by to tak mělo být :-) A hlásilo to nějaké chyby, nebo to jen vyplivlo nesmysly?

Jinak co tak koukám do manuálu, tak buď také používají u starších verzí temporary tabulku, nebo nějakou fintu max-concate a v komentářích tam jsou pak také nějaká řešení přes join se samosebou.

http://dev.mysql.com/doc/mysql/en/example-maximum-column-group-row.htm l
llook
Profil
Ono to neplive nesmysly. Podle čeho by to mělo poznat, že chci ten nejnovější záznam?

Ale ten odkaz mi hodně pomohl, už jsem ztrácel naději. Na základě toho, co tam píše ten Csaba Gabor jsem dal dohromady tohle:

SELECT v1.* FROM `versions` AS v1 LEFT JOIN `versions` AS v2 ON v1.`page_id`=v2.`page_id` AND v1.`id`<v2.`id` WHERE v2.`id` IS NULL

A když zpětné apostrofy nahradím uvozovkama, tak to funguje i v SQLite. :-)
llook
Profil
Teda vlastně takhle, chci to podle `created` a ne podle `id`:
SELECT v1.* FROM `versions` AS v1

LEFT JOIN `versions` AS v2
ON v1.`page_id`=v2.`page_id` AND v1.`created`<v2.`created`
WHERE v2.`created` IS NULL
Kajman
Profil *
No mělo to poznat podle HAVING `p.created`=`max_created`, ale možná tam bylo něco špatně :-) Jo to Csabovo řešení je taky fajn, ale nejdou tam pak dělat sum, max, count a tak :-)

Mně se líbilo to jejich řešení, jak sloučili pole pro max s něčím jiným, pak z toho udělali max a pak z toho ořízli ty původní data... to je taky mazec řešení :-)

Hlavně že to funguje :-)
llook
Profil
Ta tabulka byl výsledek dotazu bez having, jak mi radil kaifman.

To s tím HAVING vrací něco jiného - jak jsem teď zjistil, vrací jenom unikátní záznamy. U těch totiž vždycky platí created=max_created. To je asi správné chování - nejdřív se s pomocí GROUP BY seskupí a potom pomocí HAVING protřídí.

Ale to s tím JOINem funguje bezvadně.
Toto téma je uzamčeno. Odpověď nelze zaslat.

0