MySQL a výběr řádků s unikátní hodnotou

MySQL a výběr řádků s unikátní hodnotou
« kdy: 07. 10. 2011, 19:40:45 »
Mám v databázi takovouto tabulku (zjednodušeno):

Kód: [Vybrat]
+------+-------+--------+
| name | login | logout |
+------+-------+--------+
| u1   | 12:10 | 13:15  |
| u1   | 14:20 |  NULL  |
| u2   | 12:00 | 13:00  |
| u2   | 14:00 | 14:10  |
| u2   | 15:55 |  NULL  |
+------+-------+--------+

Z ní potřebuji vybrat poslední záznam ke každému identifikátoru ve sloupci name (který ale ve výpisu bude každý jen jednou) - tzn poslední aktivitu uživatelů.

Snažil jsem se použít DISTINCT, ale ten unikátnost vztahuje na celý výběr a nenapadá mě už žádné jiné řešení (ani při využití subdotazů). Rád bych se vyhnul jakémukoliv dalšímu zpracování a filtrování v aplikaci.
« Poslední změna: 07. 10. 2011, 20:15:08 od Petr Krčmář »


Re: MySQL a výběr řádků s unikátní hodnotou
« Odpověď #1 kdy: 07. 10. 2011, 20:22:35 »
Tak po nějakém válčení se mi povedlo dát dohromady tento příkaz, který (zdá se) dělá co potřebuji.
Kód: [Vybrat]
SELECT * FROM tabulka
WHERE
login=(
  SELECT MAX(login) FROM tabulka
  WHERE (
      name IN (SELECT DISTINCT name FROM tabulka)
  )
  AND logout IS NOT NULL
)
OR logout IS NULL
ORDER BY name ASC;

Pokud by ale někdo přišel na řešení s menším počtem subdotazů, dejte vědět. :-)

tefgg

Re: MySQL a výběr řádků s unikátní hodnotou
« Odpověď #2 kdy: 07. 10. 2011, 21:01:11 »
Kombinacia group by a distinct?

Re: MySQL a výběr řádků s unikátní hodnotou
« Odpověď #3 kdy: 08. 10. 2011, 09:20:19 »
Dík za postrčení, nakonec to jde i bez DISTINCT a jediným příkazem:
Kód: [Vybrat]
SELECT name, MAX(login), MAX(logout) FROM tabulka GROUP BY name ORDER BY name ASC;

pavel

Re: MySQL a výběr řádků s unikátní hodnotou
« Odpověď #4 kdy: 08. 10. 2011, 14:13:30 »
Ta poslední varianta je ale špatně. Neřeší to paralelní přihlášení (nevím, zda se mohou uživatelé přihlašovat paralelně) a neřeší to null hodnoty ve sloupci logout (které tam evidentně jsou).

Zkusím nejdřív zpřesnit zadání. Pro každé name chceme v tabulce najít řádek s maximální hodnotou login. Výsledné řádky chceme řadit vzestupně podle name. Předpokládáme, že name a login nemohou být null. Dále předpokládáme, že pro každé name existuje hledaný řádek právě jeden.

Potom lze dotaz napsat takto:
Kód: [Vybrat]
select a.*
from tabulka a inner join (
    select name, max(login) as login
    from tabulka
    group by name
) b on a.name = b.name and a.login = b.login
order by a.name

Nemám nikde po ruce MySQL, takže to nevyzkouším, ale mělo by to fungovat. Samozřejmě to lze napsat i jinak (např. s použitím IN místo joinu).


Re: MySQL a výběr řádků s unikátní hodnotou
« Odpověď #5 kdy: 09. 10. 2011, 22:23:30 »
Pavel: Máš pravdu, ty NULL hodnoty mě v tu chvíli vůbec nedošly. Každopádně tvůj příkaz funguje v pořádku, díky.

kuka

Re: MySQL a výběr řádků s unikátní hodnotou
« Odpověď #6 kdy: 10. 10. 2011, 17:32:14 »
Zalezi co je posledni aktvita uzivatele a zda je mozne paralelni prihlaseni. Pokud paralelni nelze, tak staci obycejne group by s max pro login i logout (tam vhodne osetrit null, aby byl "nejvetsi"). Pokud paralelni lze, tak posledni aktivita nezalezi (asi?) na loginu, ale na logoutu - tzn. treba reseni o kus vyse, ale ridici by byl logout.