řazení dle dvou unikátních sloupců

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
joseff
Člen | 233
+
0
-

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…

hrach
Člen | 1838
+
0
-
->group('CONCAT(name, date)')
joseff
Člen | 233
+
0
-

To bohužel opět vrátilo několik záznamů se stejným datem… :-(

Editoval joseff (11. 2. 2012 20:16)

SendiMyrkr
Člen | 30
+
0
-

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
+
0
-

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)

duke
Člen | 650
+
0
-

Co třeba takto?

SELECT * FROM records bar
WHERE NOT EXISTS (SELECT NULL FROM records foo
WHERE (bar.name = foo.name OR bar.date = foo.date) AND bar.id > foo.id)
petr.pavel
Člen | 535
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

@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ší…

joseff
Člen | 233
+
0
-

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.

SendiMyrkr
Člen | 30
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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…

22
Člen | 1478
+
0
-

A nejde to udělat poddotazem nebo přes VIEW? Nechce se mi to celé číst.. protože to je nějaký divný :D

joseff
Člen | 233
+
0
-

No doufám že to nějak jde, ale zatím nevím jak, číst to celé nemusíš, bohatě ti stačí první dotaz a tento dodatek:

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.

SendiMyrkr
Člen | 30
+
0
-

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
+
0
-

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
+
0
-

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