Tento blog je v současné době uzavřen.
Pokračování blogu na bloguje.cz jsem zrušil. Pokud budu někdy pokračovat, bude to spíš tady.
Do tabulky databáze opakovaně zaznamenávám výskyt objektu a nějaké jeho charakteristiky. Zajímá mě, jestli se (třeba v určitém časovém rozmezí) objekt vyskytoval pokaždé se stejnou charakteristikou. Sleduju třeba jméno uživatele a jeho IP adresu (nebo třeba nějaké jeho nastavení). Zajímá mě, jestli k jednomu uživateli mám, třeba i opakovaně, pořád stejné IP (nebo prostě ten druhý údaj).
Dejme tomu, že mám tabulku tabulka, která má pole id (identifikuje objekt) a vlastnost (charakteristika objektu).
Jednou z možností je řešit celý problém ve dvou krocích (tj. poddotazem). V tabulce se seskupí všechny kombinace výskytu polí id a vlastnost:
SELECT DISTINCTROW id, vlastnost FROM tabulka;
Načež řádky výše uvedeného dotazu seskupím podle id a zjistím, která id se vyskytují ve více řádcích:
SELECT id, count(*) AS pocet FROM (SELECT DISTINCTROW id, vlastnost FROM tabulka) AS poddotaz GROUP BY id HAVING pocet>1;
Řešení pomocí jednoho dotazu vychází z oblíbeného triku, kdy se tabulka propojí se sebou samotnou. Hledám případy, kdy se objekt (uživatel) vyskytuje v tabulce s různými hodnotami charakteristiky. Tedy si vyhledám dvojice záznamů, které mají stejného uživatele, ale jinou charakteristiku:
SELECT a.id AS id FROM tabulka AS a JOIN tabulka AS b ON (a.id=b.id And a.vlastnost<>b.vlastnost);
Takhle by mi dotaz vypsal všechna id, která mají v tabulce různé hodnoty pole vlastnost. Ovšem vypsal by mi je opakovaně, pro každou nalezenou dvojici hodnot charakteristiky dvakrát. Opakování se ovšem snadno odstraní doplněním DISTINCTROW:
SELECT DISTINCTROW a.id AS id FROM tabulka AS a JOIN tabulka AS b ON (a.id=b.id And a.vlastnost<>b.vlastnost);
A pokud chci vypsat ke každému objektu, u něhož se hodnota charakteristiky změnila, všechny nalezené hodnoty charakteristik, přidám do výpisu ještě jedno z polí a.vlastnost, b.vlastnost (je to jedno) a uspořádám si výpis:
SELECT DISTINCTROW a.id AS id, a.vlastnost AS vlastnost FROM tabulka AS a JOIN tabulka AS b ON (a.id=b.id And a.vlastnost<>b.vlastnost) ORDER BY id, vlastnost;
Proč vůbec píšu o napohled složité konstrukci pro jediný dotaz, když poddotaz vypadá elegantněji a u větších tabulek je méně náročný? Protože:
Máte-li vhodnou konstelaci hvězd, databáze a tabulek, klidně používejte poddotazy a tento článek berte jako kuriozitu ;-)
Vložit vlastní komentář – Návrat k článku – RSS komentářů tohoto článku
[2] 12. 8. 2005, 10:57 – Jakub Vrána (Odkaz)
Je něco špatného na dotazu "SELECT id FROM tabulka GROUP BY id HAVING COUNT(DISTINCT vlastnost) > 1"?
[3] 12. 8. 2005, 11:53 – Honza Hučín (Odkaz)
Ad [2]: Dobrý nápad. V MySQL perfektní, ale Access tomu nechce rozumět :-( Zkoušel jsem to různě uzávorkovat, na to si Access potrpí, ale nepodařilo se. Možná neumí COUNT (DISTINCT vlastnost), je trochu hloupý.
Řešení v článku (jednodotazové) funguje i pro Access.
[4] 18. 8. 2005, 13:55 – Vatoz (Odkaz)
Jednodotazová verze pro Access bez propojování tabulek existuje :
SELECT tabulka.Id, tabulka.vlastnost
FROM tabulka
GROUP BY tabulka.Id, tabulka.vlastnost
HAVING (((Count(*))>1));
[5] 18. 8. 2005, 14:14 – Honza Hučín (Odkaz)
Ad [4]: Možná jsem to špatně pochopil, ale budu-li mít v tabulce následující záznamy (v pořadí polí Id, vlastnost)
a | 1
a | 1
b | 2
c | 3
podle mě by mi vypsal a | 1. Ale přitom k Id "a" je vlastnost 1 unikátní (akorát se vyskytuje víckrát ve víc záznamech, ale to nevadí). Takže by se nemělo vypsat nic.
K tomuto článku není možné vkládat komentáře.
© Honza Hučín 2004–6
Šuplík běží na PIPNI.CZ. Díky!
8. 8. 16:48 | Pepa
7. 8. 21:26 | Honza Hučín
7. 8. 21:02 | Honza
6. 8. 14:29 | Pepa
3. 8. 18:29 | Honza
*1967, absolvent MFF UK v Praze (1991)
statistik, analytik, programátor, učitel, hudebník