řazení dle dvou unikátních sloupců
- joseff
- Člen | 233
Zdravím, potřebuji udělat dotaz aby byli dva sloupce unikátní, už nevím jak to mám udělat, zkoušel jsem vše možné, ale vždy je unikátní pouze jeden. Konkrétně potřebuji aby se ve výsledku neopakovalo datum ani název, ale když dám
->group('name, date')
tak je unikátní jen název a datumy tom jsou klidně dvakrát stejné, když to otočím tak jsou tam zase stejné názvy. Věděl by někdo jak na to? Mimochodem jsem zkoušel před názvy sloupcu dát DISTINCT a to nefunguje vůbec…
- SendiMyrkr
- Člen | 30
Pokud jsem to správně pochopil, tak mnohem snažší bude udělat dva dotazy, z hlavy mě ani nenapadá jak to napsat, možná nějakej union selectů…
Pokud tedy chápu správně to, že máš název kterej má několik datumů a zároveň datum kterej má několik názvů a chceš aby tam datum bylo vždycky jednou, bez ohledu na to jestli je pro víc názvů, a zároveň název jenom jednou, bez ohledu na to jestli je u více datumů… to co dělá hrach je že hledá unikátní kombinaci těch sloupců, to co děláš ty je že najdeš unikátní datum a k němu jednu z uvedených firem a opačně…
- joseff
- Člen | 233
Ano, je to přesně jak říkáš, no a jak by ty dva dotazy tedy měly vypadat? Mimochodem podle mě přesně k tomu je určeno DISTINCT, které mi bohužel nefunguje … :-( tím by to šlo jedním dotazem. V současnosti to ovšem neumím ani jedním, ani dvěma dotazy…
Editoval joseff (11. 2. 2012 21:32)
- petr.pavel
- Člen | 535
Přiznám se, že pořád ještě nechápu, co vlastně očekáváš za
výsledek. Pojďme se zatím bavit o tom, jaký dotaz v SQL očekáváš, a
pak vymyslíme, jak to převést do NotORM/Nette Database.
Řekněme, že máš:
id nazev datum
1 Lojza 2009-12-01
2 Tonda 2010-01-01
3 Lojza 2012-12-01
4 Tonda 2011-01-01
Tato data už sama o sobě jsou unikátní kombinace názvu a data.
Čekáš, že výsledkem dotazu bude jediná řádka? To pak musíš říct,
podle jakých kriterií vybíráš název a datum. Třeba:
SELECT MAX(nazev), MAX(datum)
.
Jestli chceš unikátní data a k nim libovolný název (nechápu využití,
ale budiž):
SELECT * FROM ... GROUP BY datum
Analogicky pro název.
Jestli potřebuješ oba výše uvedené dotazy zkombinovat, tak použij UNION. Budeš si ale muset nějak rozlišit, která řádka obsahuje ‚libovolný‘ název versus ‚unikátní‘ název a to samé pro datum. Tady si využití už fakt nedokážu představit.
SELECT 'datum' AS typ, * FROM ... GROUP BY datum
UNION
SELECT 'nazev' AS typ, * FROM ... GROUP BY nazev
- SendiMyrkr
- Člen | 30
takovej UNION jako píše petr.pavel jsem měl na mysli, každopádně rovněž nechápu k čemu je to dobrý a pokud něco takovýho musíš použít tak máš někde chybu… buď v návrhu nebo v implementaci řešení…
edit ad Distinct: používá se na začátku selectu „SELECT DISTINCT sloupec, sloupec2,…“ a myslim, že nemá vracet unikátní hodnotu, tj. sloupec, ale unikátní záznam, tj. řádek…
Editoval SendiMyrkr (12. 2. 2012 16:22)
- joseff
- Člen | 233
Pokusím se to tedy vysvětlit jasněji, výsledkem chci aby byl výběr, nikoliv řádek. A to takový výběr kde je v každém řádku unikátní datum a zároveň jě v každém řádku unikátní název. V celém výsledku se tedy bude vyskytovat každé datum pouze jednou a zároveň každý název pouze jednou. Snad je to jasné, výsledek tvé tebulky by tedy bylo:
1 Lojza 2009-12-01
2 Tonda 2010-01-01
- SendiMyrkr
- Člen | 30
můžu se zeptat na co takovou šílenost potřebuješ? a proč ti nevyhovujou dva dotazy namísto jednoho? troufám si tvrdit, že něco takovýho vytvoříš snad jenom přes temporary table…
Editoval SendiMyrkr (12. 2. 2012 16:35)
- joseff
- Člen | 233
Jde o seznam akcí, data jsou tříděná podle dalších kritérií, ale důležité je, že akce se stejným názvem se ve výpisu nesmí opakovat (jde totiž o tu samou akci jen v jiný den). Kromě toho v jednom dni může být jen jedna akce. Nepřijde mi to zas taková šílenost.
Dva dotazy mi zas tak moc nevadí, jen jsem měl dojem, že by to mělo jít jedním, což bych upřednostnil, ale jinak jsou dva dotazy vpohodě.
- duke
- Člen | 650
joseff napsal(a):
Pokusím se to tedy vysvětlit jasněji, výsledkem chci aby byl výběr, nikoliv řádek. A to takový výběr kde je v každém řádku unikátní datum a zároveň jě v každém řádku unikátní název. V celém výsledku se tedy bude vyskytovat každé datum pouze jednou a zároveň každý název pouze jednou. Snad je to jasné, …
Jasné je pouze to, že to není jasné ani tobě.
Z tvého „výběr kde je v každém řádku unikátní datum a zároveň
jě v každém řádku unikátní název“ nijak nevyplývá, že
„V celém výsledku se tedy bude vyskytovat každé datum pouze jednou a
zároveň každý název pouze jednou.“
Vždyť i výsledek, který uvádíš, nevyhovuje těmto tvrzením, neboť se v něm nevyskytuje např. datum „2012–12–01“ (každé datum se tam má vyskytovat jednou).
Nicméně pokud jsem tě dobře pochopil, a chceš prostě vyřadit řádky, které by opakovali buď jméno nebo datum některého z předchozích řádků, pak by měl fungovat ten dotaz, který jsem uvedl v předchozí odpovědi. Nicméně ještě by to šlo jednodušeji, pokud bys upřesnil, jaké datum chceš preferovat v případě více možností. Pokud by ti stačilo např. nejstarší, tak bys mohl použít i dotaz:
SELECT nazev, MIN(datum) AS prvni_datum FROM akce GROUP BY nazev
Původní dotaz preferoval názvy a datumy z řádků s nižším ID.
Editoval duke (12. 2. 2012 20:40)
- joseff
- Člen | 233
@duke
No mě to jasné je, jen bojuji s tím SQL :-D
Vždyť i výsledek, který uvádíš, nevyhovuje těmto tvrzením, neboť se v něm nevyskytuje např. datum „2012–12–01“ (každé datum se tam má vyskytovat jednou).
Takže ještě jednou, jelikož musí být název unikátní v celém výběru a ve výsledku se již objevil Lojza i Tonda, nemůže tam být znovu Lojza! Nehledě na datu.
Tvůj příklad zase vrací několik záznamů se stejným datem (tedy datum není unikátní ve výběru – viz mé vysvětlení minule). Snad už je to jasnější…
- SendiMyrkr
- Člen | 30
Ber to z pohledu, že je lepší i udržitelnější udělat dva naprsto jednoduchý dotazy než vymýšlet nějakou šílenost do který když sáhneš tak nevíš jestli to pak bude fungovat správně. jako šílenost nevidim to co potřebuješ, ale to, že se to snažíš udělat jednim dotazem. Věř mi, nic hezkýho ti to nepřinese. Pokud vyhovují dva dotazy jednoduchý dotazy ta nevidim důvod proč se snažit vymyslet něco tak komplikovanýho… a podle mých znalostí nemožnýho… Hlavně nechápu, proč, když může být v jednom dni jenom jedna akce umožňuješ ukládat více akcí, ale to už s původnim dotazem asi nesouvisí…
- RiskyNet
- Člen | 20
joseff napsal(a):
Zkraceně: chci aby se ve výsledku objevil každý datum pouze jednou v celém výběru a každý název pouze jednou v celém výběru.
Když vezmu vzorovou tabulku co se tady objevila, udělám možná to, co požaduješ jednoduše (a už to tady bylo od duke)
SELECT DISTINCT `name`, `datum` FROM `test` GROUP BY `name`
Podmínkou na den/měsíc/rok se dá dál upravovat. Otázkou je, jestli a) dobře chápu co cheš b) jestli je to tabulka správné struktury nebo má návaznosti
Jediné, co jsem z toho co popisuješ pochopil je to, že struktura je zřejmě špatně (opravu do každého řádku ukládáš název „akce“ a na to celé děláš dotazy?), ale do aplikace nevidím, může to mít nějaký důvod. Určitě by to ale strukturu chtělo promyslet a případně upravit.
Editoval RiskyNet (12. 2. 2012 22:03)
- joseff
- Člen | 233
RiskyNet napsal(a):
Když vezmu vzorovou tabulku co se tady objevila, udělám možná to, co požaduješ jednoduše (a už to tady bylo od duke)
SELECT DISTINCT `name`, `datum` FROM `test` GROUP BY `name`
To bohužel vrátí více záznamů se stejným datem… (samozřejmě ne ze vzorové tabulky, protože tam stejná data nejsou…)
- joseff
- Člen | 233
SendiMyrkr napsal(a):
Ber to z pohledu, že je lepší i udržitelnější udělat dva naprsto jednoduchý dotazy než vymýšlet nějakou šílenost do který když sáhneš tak nevíš jestli to pak bude fungovat správně. jako šílenost nevidim to co potřebuješ, ale to, že se to snažíš udělat jednim dotazem. Věř mi, nic hezkýho ti to nepřinese. Pokud vyhovují dva dotazy jednoduchý dotazy ta nevidim důvod proč se snažit vymyslet něco tak komplikovanýho… a podle mých znalostí nemožnýho… Hlavně nechápu, proč, když může být v jednom dni jenom jedna akce umožňuješ ukládat více akcí, ale to už s původnim dotazem asi nesouvisí…
Já to tak moc rád vezmu a moc rád udělám dva dotazy, ale stále nevím jak, stále tu není funkční řešení ani se dvěma dotazy…
- iguana007
- Člen | 970
Pokud bych vycházel z příkladu, že pracuješ se sloupci jméno a datum, tak by se to dalo vyřešit takto:
SELECT name, MAX(date) FROM table GROUP BY name
V případě, že by si chtěl nejnovější záznam. Pokud by si chtěl nejstarší, tak nahradíš MAX za MIN.
Editoval iguana007 (12. 2. 2012 22:47)
- joseff
- Člen | 233
iguana007 napsal(a):
Pokud bych vycházel z příkladu, že pracuješ se sloupci jméno a datum, tak by se to dalo vyřešit takto:
SELECT name, MAX(datum) FROM tabulka GROUP BY name
V případě, že by si chtěl nejnovější záznam. Pokud by si chtěl nejstarší, tak nahradíš MAX za MIN.
To ovšem vrátí několik záznamů se stejným datem…
- SendiMyrkr
- Člen | 30
co ti to má vrátit pokud máš pouze jeden název a dva různý datumy?
1. název - 2012-01-02
2. název - 2012-01-03
a co třeba
1. název - 2012-01-02
2. název - 2012-01-03
3. název2 - 2012-01-03
4. název3 - 2012-01-03
Editoval SendiMyrkr (13. 2. 2012 1:52)
- joseff
- Člen | 233
SendiMyrkr napsal(a):
co ti to má vrátit pokud máš pouze jeden název a dva různý datumy?
1. název - 2012-01-02 2. název - 2012-01-03
a co třeba
1. název - 2012-01-02 2. název - 2012-01-03 3. název2 - 2012-01-03 4. název3 - 2012-01-03
V prvnim pripade jeden radek (ten prvni) a v druhem pripade prvni a treti radek.
- duke
- Člen | 650
joseff napsal(a):
Takže ještě jednou, jelikož musí být název unikátní v celém výběru a ve výsledku se již objevil Lojza i Tonda, nemůže tam být znovu Lojza! Nehledě na datu.
Aby bylo tvé zadání jednoznačné, je třeba, abys upřesnil, které ze jmen se má preferovat v případě shody v datumech a které datum se má preferovat v případě shody ve jménech.
Tvůj příklad zase vrací několik záznamů se stejným datem (tedy datum není unikátní ve výběru – viz mé vysvětlení minule). Snad už je to jasnější…
Pravda. Takže výsledek je znovu třeba zgroupovat a přidat kritérium pro výběr jména. Tj. např.:
SELECT MIN(nazev) as preferovane_jmeno, preferovane_datum
FROM (
SELECT nazev, MIN(datum) AS preferovane_datum
FROM akce
GROUP BY nazev
) AS foo
GROUP BY preferovane_datum
Pro úplnost dodám, že můj původní příklad pomocí NOT EXISTS je nevyhovující, protože nefiltruje podle toho, co bylo vybráno, ale podle toho, co existuje (což není vždy totéž).