Fórum Root.cz

Hlavní témata => Software => Téma založeno: Zopper 07. 10. 2011, 19:40:45

Název: MySQL a výběr řádků s unikátní hodnotou
Přispěvatel: Zopper 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.
Název: Re: MySQL a výběr řádků s unikátní hodnotou
Přispěvatel: Zopper 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. :-)
Název: Re: MySQL a výběr řádků s unikátní hodnotou
Přispěvatel: tefgg 07. 10. 2011, 21:01:11
Kombinacia group by a distinct?
Název: Re: MySQL a výběr řádků s unikátní hodnotou
Přispěvatel: Zopper 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;
Název: Re: MySQL a výběr řádků s unikátní hodnotou
Přispěvatel: pavel 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).
Název: Re: MySQL a výběr řádků s unikátní hodnotou
Přispěvatel: Zopper 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.
Název: Re: MySQL a výběr řádků s unikátní hodnotou
Přispěvatel: kuka 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.