Šuplík Honzy Hučína

Skok na navigaci (menu)

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.

Komentovaný článek

Internet a vše kolem
12. 8. 2005

Kontrola unikátnosti jedním SQL dotazem

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).

Nejprve řešení poddotazem

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í jedním dotazem

Ř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;

Jeden krok, nebo dva?

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:

  • poddotazy v některých verzích databází nefungují (v MySQL až od verze 4.1),
  • některé způsoby výpisu se pomocí poddotazu zařídí obtížně,
  • je to zajímavý oříšek na přemýšlení.

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ánkuRSS komentářů tohoto článku

Komentáře

[1] 12. 8. 2005, 10:40 – Michal

...smazáno na žádost autora...

[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!

sber.cermat.cz

RSS Šuplíku

RSS komentářů – souhrnně

U každého článku je samostatný RSS kanál pro komentáře.

Výběr článků

Posledních 10 článků

nebo podle data:

nebo hledání fulltextem:

Archiv všech článků

Poslední komentáře

Zabili mě, parchanti [2]

8. 8. 16:48 | Pepa

Cestou kolem blogu [2]

7. 8. 21:26 | Honza Hučín

Cestou kolem blogu [1]

7. 8. 21:02 | Honza

Vrtulník nad hlavou [3]

6. 8. 14:29 | Pepa

Taková hra na volby [1]

3. 8. 18:29 | Honza

Nejčtenější

Žádné údaje nejsou k dispozici.

O mně

*1967, absolvent MFF UK v Praze (1991)

statistik, analytik, programátor, učitel, hudebník

nyní Ústav pro informace ve vzdělávání

Životopis (RTF)

Napište mi