Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Petr 14. 10. 2018, 07:31:56

Název: Proč nefunguje tento SQL dotaz
Přispěvatel: Petr 14. 10. 2018, 07:31:56
Proč mi nefunguje následující dotaz?
SELECT z.name, i.zkr
FROM Zam z LEFT OUTER JOIN Info i ON z.id_z=i.id_z
WHERE i.datum>1561939200 OR
      i.datum=NULL

Chtěl bych dosáhnout toho, aby se mi pro každého zam vypsalo info od zadaného data pokud existuje a pokud žádne info pro příslušné data neexistuje, tak aby se jednou vypsal samotný zam s tím, ze info bude null.

Když pominu nepodstatné, tak tabulka Zam má sloupce id_z a name (id_z je prim. klíč) a tabulka Info má sloupce id_z, datum a zkr (id_z a datum je prim. klíč).

Děkuji pěkně.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Petr 14. 10. 2018, 07:42:17
Proč mi nefunguje následující dotaz?
SELECT z.name, i.zkr
FROM Zam z LEFT OUTER JOIN Info i ON z.id_z=i.id_z
WHERE i.datum>1561939200 OR
      i.datum=NULL

Chtěl bych dosáhnout toho, aby se mi pro každého zam vypsalo info od zadaného data pokud existuje a pokud žádne info pro příslušné data neexistuje, tak aby se jednou vypsal samotný zam s tím, ze info bude null.

Když pominu nepodstatné, tak tabulka Zam má sloupce id_z a name (id_z je prim. klíč) a tabulka Info má sloupce id_z, datum a zkr (id_z a datum je prim. klíč).

Děkuji pěkně.

Dotaz jsem napsal nejasně. Já vlastně vím proč to nefunguje. Nefunguje to proto, že se nejprve propojí tabulky, kde každý zam má nějaké info, takže tam žádné null není. Pak se uplatní filtr na datum a ten mi vyřadí všechny zam, kteří nemají info od příslušného data. Takže já bych potřeboval nejprve vyfiltrovat info podle data a pak teprve dělat left outer join, ale nevím jak říct, aby se nejprve uplatnilo where a až potom join.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Janci 14. 10. 2018, 07:48:26
Lebo na NULL sa neporovnava cez =, ale operarorom IS NULL.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Petr 14. 10. 2018, 07:51:45
Lebo na NULL sa neporovnava cez =, ale operarorom IS NULL.
Pravda, to jsem tady napsal blbě.

A už jsem přišel i na řešení svého problému, tu podmínku na datum musím napsat za ON místo do WHERE, tím ji vyfiltruji před spojením. Děkuji.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: db 14. 10. 2018, 08:54:43
Lebo na NULL sa neporovnava cez =, ale operarorom IS NULL.
Pravda, to jsem tady napsal blbě.

A už jsem přišel i na řešení svého problému, tu podmínku na datum musím napsat za ON místo do WHERE, tím ji vyfiltruji před spojením. Děkuji.

To IS NULL je jasné, ale přesunout podmínku za ON? Co to je za databázi?
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Pavel... 14. 10. 2018, 12:08:09
To IS NULL je jasné, ale přesunout podmínku za ON? Co to je za databázi?

Mozno nejaka obskurna DB to neda, ale je to uplne normalna vec.

Zakladna logika toho je v tom, ze ked robite povedzme full join, tak ked chcete v tej casti kde sa vam doplna "nic" robit podmienky, tak to vo WHERE klauzule robi pomerne blbo.
Uplne logicky to mozte strcit do ON, tak isto ako je tam ta podmienka na IDcka.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: grgs 14. 10. 2018, 12:17:07
Proč mi nefunguje následující dotaz?
SELECT z.name, i.zkr
FROM Zam z LEFT OUTER JOIN Info i ON z.id_z=i.id_z
WHERE i.datum>1561939200 OR
      i.datum=NULL

Chtěl bych dosáhnout toho, aby se mi pro každého zam vypsalo info od zadaného data pokud existuje a pokud žádne info pro příslušné data neexistuje, tak aby se jednou vypsal samotný zam s tím, ze info bude null.

Když pominu nepodstatné, tak tabulka Zam má sloupce id_z a name (id_z je prim. klíč) a tabulka Info má sloupce id_z, datum a zkr (id_z a datum je prim. klíč).

Děkuji pěkně.

to datum zrovna pustili z ústavu? uvozovky? nic?

ty tabulky vazne s velbloudi notaci?

do joinu rvat podminky na datum? ok no
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Kit 14. 10. 2018, 12:52:42
to datum zrovna pustili z ústavu? uvozovky? nic?
ty tabulky vazne s velbloudi notaci?
do joinu rvat podminky na datum? ok no

K čemu uvozovky, když se tam nepoužívá žádný string ani datum?

Kde je nějaká velbloudí notace? V ukázce žádnou nevidím.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: grgs 14. 10. 2018, 14:29:13
to datum zrovna pustili z ústavu? uvozovky? nic?
ty tabulky vazne s velbloudi notaci?
do joinu rvat podminky na datum? ok no

K čemu uvozovky, když se tam nepoužívá žádný string ani datum?

Kde je nějaká velbloudí notace? V ukázce žádnou nevidím.

pokud ma tazatel pod atributem datum schovany cislo ponozek, budiz, chtel bych to ve firme jako db architekta

predpokladam ze dalsi slovo v nazvu tabulky by zacinalo velkym pismenem.. pokud ne, bylo by to snad jeste horsi
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Filip Jirsák 14. 10. 2018, 15:42:31
tu podmínku na datum musím napsat za ON místo do WHERE, tím ji vyfiltruji před spojením
JOIN … ON je akorát modernější zápis podmínky ve WHERE pro spojování tabulek. Takže na tom, kam tu podmínku napíšete, nezáleží.

Problém v tom příkazu je jenom v tom porovnání s NULL hodnotou, kde se musí použít IS NULL a ne rovná se.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Kit 14. 10. 2018, 15:48:03
to datum zrovna pustili z ústavu? uvozovky? nic?
ty tabulky vazne s velbloudi notaci?
do joinu rvat podminky na datum? ok no
Kde je nějaká velbloudí notace? V ukázce žádnou nevidím.
predpokladam ze dalsi slovo v nazvu tabulky by zacinalo velkym pismenem.. pokud ne, bylo by to snad jeste horsi

To by ale nebyla velbloudí notace.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: j 14. 10. 2018, 16:06:51
JOIN … ON je akorát modernější zápis podmínky ve WHERE pro spojování tabulek. Takže na tom, kam tu podmínku napíšete, nezáleží.
....
Zase Jirsak meles o vecech o kterych vis kulovy? Ten select se chova uplne jinak. Kdyz se podminka napise rovnou do join, tak se spojovani provadi uz nad omezenym poctem zaznamu, vs where, kde se nejdriv spoji vsechno a teprve pak se to omezuje, coz bude v drtivy vetsine pripadu radove pomalejsi.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: grgs 14. 10. 2018, 16:13:49
to datum zrovna pustili z ústavu? uvozovky? nic?
ty tabulky vazne s velbloudi notaci?
do joinu rvat podminky na datum? ok no
Kde je nějaká velbloudí notace? V ukázce žádnou nevidím.
predpokladam ze dalsi slovo v nazvu tabulky by zacinalo velkym pismenem.. pokud ne, bylo by to snad jeste horsi

To by ale nebyla velbloudí notace.

prosim zjisti si o tom neco
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: agent 14. 10. 2018, 16:23:31
To jsou datumy v té databázi opravdu uložené takhle hnusně jako sekundy od 1.1.1970?
Není pro programátora přehlednější použít raději něco jako date < '2019-07-10' (přípdně DATEDIFF(...) < 0) pokud neumí pro datumy přímo < <= > >= operátory?
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Filip Jirsák 14. 10. 2018, 16:27:32
Zase Jirsak meles o vecech o kterych vis kulovy? Ten select se chova uplne jinak. Kdyz se podminka napise rovnou do join, tak se spojovani provadi uz nad omezenym poctem zaznamu, vs where, kde se nejdriv spoji vsechno a teprve pak se to omezuje, coz bude v drtivy vetsine pripadu radove pomalejsi.
Děkuji za potvrzení. Ano, v normální SQL databázi se to chová tak, že způsob zápisu dotazu vůbec nemá vliv na to, jak dotaz databáze vyhodnotí. To, jak přesně se dotaz provede – v jakém pořadí se budou načítat data pro jednotlivé tabulky, zda se použijí indexy nebo fullscan atd. – určuje plánovač dotazu. Je to asi ta největší přednost SQL databází a důvod, proč jsou tak úspěšné – databázový stroj tu optimalizaci dotazu v drtivé většině případů zvládá mnohem lépe, než člověk.

Jak už jsem psal, JOIN je jen modernější zápis podmínek pro spojování tabulek. Ve skutečnosti reprezentace dotazu pro plánovač už mezi zápisem s JOIN a s WHERE nerozlišuje, je to opravdu jen rozdíl v zápisu.

Samozřejmě se to týká pořádných SQL databází, pokud si někdo napíše nějakou samo-domo databázi, která nemá žádný plánovač dotazů a jenom tupě rovnou z parseru načítá data, tam to na pořadí zápisu záviset může.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Kit 14. 10. 2018, 16:35:34
to datum zrovna pustili z ústavu? uvozovky? nic?
ty tabulky vazne s velbloudi notaci?
do joinu rvat podminky na datum? ok no
Kde je nějaká velbloudí notace? V ukázce žádnou nevidím.
predpokladam ze dalsi slovo v nazvu tabulky by zacinalo velkym pismenem.. pokud ne, bylo by to snad jeste horsi

To by ale nebyla velbloudí notace.

prosim zjisti si o tom neco

Ano, zjistil jsem, že PascalCase vypadá jinak než camelCase.

Prosím, zjisti si o tom něco.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: hrgd 14. 10. 2018, 18:38:33
to datum zrovna pustili z ústavu? uvozovky? nic?
ty tabulky vazne s velbloudi notaci?
do joinu rvat podminky na datum? ok no
Kde je nějaká velbloudí notace? V ukázce žádnou nevidím.
predpokladam ze dalsi slovo v nazvu tabulky by zacinalo velkym pismenem.. pokud ne, bylo by to snad jeste horsi

To by ale nebyla velbloudí notace.

prosim zjisti si o tom neco

Ano, zjistil jsem, že PascalCase vypadá jinak než camelCase.

Prosím, zjisti si o tom něco.

upper-CamelCase a lower-CamelCase, furt nic? otevri uz ten google prosim
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Pavel... 14. 10. 2018, 20:09:13
Jak už jsem psal, JOIN je jen modernější zápis podmínek pro spojování tabulek. Ve skutečnosti reprezentace dotazu pro plánovač už mezi zápisem s JOIN a s WHERE nerozlišuje, je to opravdu jen rozdíl v zápisu.

Navrhujem skuste si skor ako napisete nieco to aj overit.
Je principialny rozdiel medzi tym ked date podmienku do ON a WHERE. Vyhodnoti sa to radikalne inak.

pre povedzme "a outer join b":
ked date a.id=b.id do WHERE, vrati vam to riadky kde su zaznamy v oboch tabulkach.
ked date to iste do ON, vrati vam to aj pripady ked v jednej z tych tabuliek zaznam neexistuje
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Filip Jirsák 14. 10. 2018, 20:56:27
Navrhujem skuste si skor ako napisete nieco to aj overit.
Navrhuju kuste si dřív, než něco napíšete, něco o tom zjistit a ověřit si to.

Je principialny rozdiel medzi tym ked date podmienku do ON a WHERE. Vyhodnoti sa to radikalne inak.
Nikoli, je to pouze rozdíl v zápisu. V exekučním plánu to nijak nepoznáte. Některé databáze ten rozdíl myslím setřou už v době parsování dotazu.

pre povedzme "a outer join b":
ked date a.id=b.id do WHERE, vrati vam to riadky kde su zaznamy v oboch tabulkach.
ked date to iste do ON, vrati vam to aj pripady ked v jednej z tych tabuliek zaznam neexistuje
No jo, to byste ale musel umět napsat OUTER JOIN. To, co jste napsal do WHERE, je INNER JOIN.

Následující zápisy jsou ekvivalentní (stará syntaxe OUTER JOINU je v syntaxi Oracle – pochází z doby, kdy JOIN ještě nebyl standardizován):
Kód: [Vybrat]
SELECT * FROM a LEFT OUTER JOIN b ON a.id = b.id;
SELECT * FROM a, b WHERE a.id = b.id(+);

Pokud nevěříte mně, např. v článku [ ( LEFT|RIGHT [ OUTER ])| INNER ] JOIN v SQL (https://www.root.cz/clanky/leftright-outer-inner-join-v-sql/)to psal Pavel Stěhule:

Citace
Není žádný rozdíl ve výkonnosti mezi použitím JOINu a původním zápisem pro spojení tabulek. Pamatuji doby, kdy se JOIN nepoužíval právě z obavy o ztrátu výkonu. To je nesmysl. Liší se pouze zápis. Smysl a provádění je stejné.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: dw 14. 10. 2018, 22:07:10
Jak už jsem psal, JOIN je jen modernější zápis podmínek pro spojování tabulek. Ve skutečnosti reprezentace dotazu pro plánovač už mezi zápisem s JOIN a s WHERE nerozlišuje, je to opravdu jen rozdíl v zápisu.

Navrhujem skuste si skor ako napisete nieco to aj overit.
Je principialny rozdiel medzi tym ked date podmienku do ON a WHERE. Vyhodnoti sa to radikalne inak.

pre povedzme "a outer join b":
ked date a.id=b.id do WHERE, vrati vam to riadky kde su zaznamy v oboch tabulkach.
ked date to iste do ON, vrati vam to aj pripady ked v jednej z tych tabuliek zaznam neexistuje

No... MySQL nie je nastastie jedina databaza, je tu dostatok DB ktorych planovac zvladne zaradit podmienku pred spojovanie aj ked ju ma az vo where...
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Pavel Stěhule 14. 10. 2018, 22:44:34
JOIN … ON je akorát modernější zápis podmínky ve WHERE pro spojování tabulek. Takže na tom, kam tu podmínku napíšete, nezáleží.
....
Zase Jirsak meles o vecech o kterych vis kulovy? Ten select se chova uplne jinak. Kdyz se podminka napise rovnou do join, tak se spojovani provadi uz nad omezenym poctem zaznamu, vs where, kde se nejdriv spoji vsechno a teprve pak se to omezuje, coz bude v drtivy vetsine pripadu radove pomalejsi.

Určitě není jedno, kam se zapíše predikát - v případě OUTER JOINů to může mít vliv na výsledek - je tam jiná sémantika. Zrovna tak ale není pravda, že by se napřed vyhodnocoval JOIN a poté WHERE. Databáze se snaží o push down predikátů - tj jakékoliv filtry - bez ohledu na to jestli jsou v JOINu nebo ve WHERE natlačit co nejhlouběji v prováděcím plánu - snažíte se omezit data ještě než s nimi cokoliv začnete dělat, případně se díky predikátům na úrovni listu stromu prováděcího plánu mohou vybrat indexy, které mohou rovnou vracet data po aplikování filtru.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Pavel... 14. 10. 2018, 23:27:50
Následující zápisy jsou ekvivalentní (stará syntaxe OUTER JOINU je v syntaxi Oracle – pochází z doby, kdy JOIN ještě nebyl standardizován):
Kód: [Vybrat]
SELECT * FROM a LEFT OUTER JOIN b ON a.id = b.id;
SELECT * FROM a, b WHERE a.id = b.id(+);

Pokud nevěříte mně, např. v článku [ ( LEFT|RIGHT [ OUTER ])| INNER ] JOIN v SQL (https://www.root.cz/clanky/leftright-outer-inner-join-v-sql/)to psal Pavel Stěhule:

Citace
Není žádný rozdíl ve výkonnosti mezi použitím JOINu a původním zápisem pro spojení tabulek. Pamatuji doby, kdy se JOIN nepoužíval právě z obavy o ztrátu výkonu. To je nesmysl. Liší se pouze zápis. Smysl a provádění je stejné.

au...
a) skuste si precitat co pise Vami odkazovany text: "vykonnostny rozdiel".
b) pouzit Oracle syntax, ktora je syntakticky cukor ako agument, znaci, ze ocividne netusite o com pisete.
c) ano, vami uvedene dve SQLka nemaju prakticky rozdiel, ale to sa samozrejme netyka toho na co reagujete.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Filip Jirsák 15. 10. 2018, 07:43:05
a) skuste si precitat co pise Vami odkazovany text: "vykonnostny rozdiel".
Já jsem to samozřejmě četl, a na rozdíl od vás až do konce. „Liší se pouze zápis. Smysl a provádění je stejné.“

b) pouzit Oracle syntax, ktora je syntakticky cukor ako agument, znaci, ze ocividne netusite o com pisete.
Ta Oracle syntax je starší, než JOIN ve standardu. Syntaktický cukr je naopak klíčové slovo ON ve standardu – v případě INNER JOIN se podmínka, která se za ON napíše, jenom pomocí AND připojí k ostatním podmínkám ve WHERE. V případě OUTER JOINu je to to samé, akorát se ta podmínka samozřejmě z INNER JOIN predikátu musí změnit na OUTER JOIN. K tomu JOINu se podmínka pomocí ON připojuje jenom kvůli přehlednosti, klidně tam můžete dát podmínku, která se spojovaných tabulek nijak netýká, a naopak klidně podmínku pro spojení tabulek můžete dát do WHERE.

c) ano, vami uvedene dve SQLka nemaju prakticky rozdiel, ale to sa samozrejme netyka toho na co reagujete.
Samozřejmě se to týká toho, na co reaguju. Ten příkaz po změně porovnání NULL hodnoty na IS NOT NULL je naprosto správně, oba následující dotazy jsou ekvivalentní a budou mít stejný prováděcí plán:

Kód: [Vybrat]
SELECT z.name, i.zkr
FROM Zam z
  LEFT JOIN Info i
    ON z.id_z=i.id_z
WHERE (i.datum > 1561939200 OR i.datum IS NULL);

SELECT z.name, i.zkr
FROM Zam z
  LEFT JOIN Info i
    ON z.id_z=i.id_z AND i.datum > 1561939200
;
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: lt 15. 10. 2018, 11:00:47
Tie sqlka nie su rovnake ani nahodou .. kazdy moze vratit rozny pocet riadkov.

Ten druhy vrati celu mnozinu prvej tabulky, data z druhej vrati len podla outer join podmienky.
Ten prvy ale vrati z mnoziny prvej tabulky len tie, kedy nenajoinuje druhu, plus tie, ktore sice najoinuje, ale plati podmienka datum>{cislo}

Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Filip Jirsák 15. 10. 2018, 13:09:40
Máte pravdu. Ztratil jsem se v tom, co Petr vlastně chce. Pokud chce vypsat všechny zaměstnance, a k nim pouze novější informace, pokud existují, pak je to:

Kód: [Vybrat]
SELECT z.name, i.zkr
FROM Zam z
  LEFT JOIN Info i
    ON z.id_z=i.id_z AND i.datum > 1561939200
;

SELECT z.name, i.zkr
FROM Zam z, Info i
WHERE i.id_z (+) = z.id_z AND i.datum (+) > 1561939200;
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Petr 17. 10. 2018, 06:18:28
Koukám co se tu rozpoutalo po mém dotazu. Divím se té nevraživosti některých, buďte v pohodě. K dotazům a poznámkám, co zde zazněly.

Jedná se o databázi Oracle.

Ano, datum je unix timestamp, aplikace s ním pracuje takto, nevidím důvod proč ho takto neukládat i v databázi.

Co se týče velikosti písmen, je mým zvykem psát sql konstrukce velkými písmeny (SELECT), tabulky s velkými prvními písmeny a atributy malými. Databázi je to jedno a mě to pomáhá se lépe orientovat.

Databáze v mém dotazu zaručeně vrací jiné výsledky podle toho, zda podmínku na datum napíšu za ON nebo za WHERE a doufám, že je to zaručené a nějaký exekuční plán nemůže měnit náhodně vrácené výsledky.
Název: Re:Proč nefunguje tento SQL dotaz
Přispěvatel: Filip Jirsák 17. 10. 2018, 07:14:12
Databáze v mém dotazu zaručeně vrací jiné výsledky podle toho, zda podmínku na datum napíšu za ON nebo za WHERE a doufám, že je to zaručené a nějaký exekuční plán nemůže měnit náhodně vrácené výsledky.
Různé exekuční plány pro stejný dotaz samozřejmě musí vracet stejnou sadu záznamů. Když pouze přesunete zápis vaší podmínky z WHERE do ON u LEFT JOINU, změníte tu podmínku z INNER JOIN podmínky na LEFT JOIN podmínku. To jsou dvě různé podmínky, tedy (obecně) různé výsledky. Moje připomínka nebyla o tom, že můžete zaměňovat INNER JOIN a OUTER JOIN podmínky, to samozřejmě ne. Upozorňoval jsem, že nezáleží na tom, zda podmínku napíšete k ON nebo do WHERE – musí to ale být vždy ta stejná podmínka. Tedy pokud máte podmínku u LEFT JOIN … ON, musíte ji při přesunu do WHERE upravit na zápis LEFT JOIN podmínky ve WHERE. Ten ANSI SQL:99 zápis joinů (s klíčovým slovem JOIN) přidává pomocí příslušných klíčových slov informaci o případném OUTER JOINu přímo k tomu klíčovému slovu JOIN, takže se to neuvádí už přímo u predikátu – při přesunu do WHERE tedy musíte ten příznak, že jde o OUTER JOIN, přidat přímo k tomu predikátu.

Nejjeednodušší je to samozřejmě u INNER JOINů, protože ty jsou ve WHERE defaultní a není potřeba k nim přidávat žádný příznak, takže příslušný predikát můžete opravdu jen přesouvat volně mezi ON a WHERE bez jakýchkoli úprav.