MySQL - podmíněný SELECT přes dvě tabulky

MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 04. 10. 2019, 10:53:03 »
Potřeboval bych provést SELECT dotaz nad jednou tabulkou tbl1.id_data, který je podmíněn jinou tabulkou tbl2,
tedy z tbl1.id_data vybrat pouze to, co v tbl2 je jako allowed >0
S tím, že tbl2.id_data nemusí obsahovat všechny data v tbl1.id_data

Díky za pomoc

Kód: [Vybrat]
tbl1
-------
id_data
-------
100
101

tbl2
-------
id_data|allowed
100    |0
101    |1


Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #1 kdy: 04. 10. 2019, 11:15:05 »
inner join + filtr

3ugeene

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #2 kdy: 04. 10. 2019, 11:32:03 »
Kód: [Vybrat]
SELECT * FROM tbl1 AS t1

INNER JOIN tbl2 AS t2
USING id_data

WHERE t2.allowed

e3k

  • ***
  • 236
    • Zobrazit profil
    • E-mail
Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #3 kdy: 04. 10. 2019, 12:19:30 »
>>>S tím, že tbl2.id_data nemusí obsahovat všechny data v tbl1.id_data
v tom pripade nepojde o INNER JOIN ale o LEFT OUTER JOIN

ale da sa aj subselect:

Kód: [Vybrat]
select * from tbl1 as t1
where t1.id_data NOT IN (select t2.id_data from tlb2 as t2 where t2.allowed = 0)

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #4 kdy: 04. 10. 2019, 12:35:15 »
ale da sa aj subselect:

Ale fuj, to bude mnohem pomalejší. Na tento příklad je jediným správným řešením LEFT JOIN + WHERE.


gill

  • ****
  • 270
    • Zobrazit profil
    • E-mail
Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #5 kdy: 04. 10. 2019, 12:55:24 »
ale da sa aj subselect:

Ale fuj, to bude mnohem pomalejší. Na tento příklad je jediným správným řešením LEFT JOIN + WHERE.

proč left join?

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #6 kdy: 04. 10. 2019, 17:09:29 »
Kód: [Vybrat]
SELECT tbl1.* FROM tbl1
  INNER JOIN tbl2 ON tbl1.id_data = tbl2.id_data
  WHERE t2.allowed>0

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #7 kdy: 04. 10. 2019, 17:37:10 »
proč left join?

Left join tam musí být, viz zadání úkolu: "S tím, že tbl2.id_data nemusí obsahovat všechny data v tbl1.id_data"

RDa

  • *****
  • 2 570
    • Zobrazit profil
    • E-mail
Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #8 kdy: 04. 10. 2019, 17:56:34 »
Otazka ktera mela padnout - pokud druha tabulka neobsahuje allowed pro urcity prvek z prvni tabulky, povazuje se to za hodnotu allowed 0 nebo 1 ? Nebo je nutno take vedet, ze tato vlatnost nebyla nastavena?

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #9 kdy: 04. 10. 2019, 18:11:12 »
Otazka ktera mela padnout - pokud druha tabulka neobsahuje allowed pro urcity prvek z prvni tabulky, povazuje se to za hodnotu allowed 0 nebo 1 ? Nebo je nutno take vedet, ze tato vlatnost nebyla nastavena?

Správná připomínka.

Z hlediska SQL se to považuje za NULL.

Myslím, že sémanticky správný je LEFT JOIN.
Následuje filtr WHERE, kde může být allowed > 0, nebo IS NULL, nebo nějaká jiná podmínka.

Pokud je podmínka WHERE allowed > 0, pak je zcela jedno, jestli se jedná o LEFT nebo INNER join. Ve chvíli, kdy by byla podmínka např. WHERE allowed = 0 OR allowed IS NULL, pak už by se rozdíl mezi LEFT a INNER projevil.

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #10 kdy: 05. 10. 2019, 17:29:54 »
Myslím, že sémanticky správný je LEFT JOIN.
Co je sémanticky správně musí napsat Racchek. Napsal „vybrat pouze to, co v tbl2 je jako allowed >0“, to by vedlo na INNER JOIN. Pak ale doplnil, že tbl2 nemusí obsahovat všechny záznamy z tbl1 – že uvedl tuhle informaci by vedlo na OUTER JOIN, ale je možné, že ji doplnil jen z neznalosti „pro jistotu, co kdyby to na řešení mělo vliv“.

Pro Raccheka – ke spojení několika tabulek do jednoho dotazu se v SQL používá klauzule JOIN, která má různé varianty. Je to úplný základ relačních databází, bez znalosti JOINu nemá smysl se s relační databází o cokoli pokoušet. Pokud se chcete naučit základy používání relačních databází, kupte si o tom nějakou knížku, vyšlo jich dost.

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #11 kdy: 05. 10. 2019, 18:26:30 »
Napsal „vybrat pouze to, co v tbl2 je jako allowed >0“, to by vedlo na INNER JOIN. Pak ale doplnil, že tbl2 nemusí obsahovat všechny záznamy z tbl1 – že uvedl tuhle informaci by vedlo na OUTER JOIN, ale je možné, že ji doplnil jen z neznalosti „pro jistotu, co kdyby to na řešení mělo vliv“.

No právě protože "co kdyby" je dané jako premisa (tbl2 nemusí obsahovat záznamy), je určitě lepší praxe provést OUTER JOIN a omezení dát do WHERE. Do JOINU patří definice struktury dat, do WHERE podmínky. Pokud by použil INNER JOIN, tak by část podmínky de facto přesunul do klauzule JOIN. To se nedá doporučit, SQL by mělo být čitelné a podmínky by měly být zejm. ve WHERE. Kdyby se do budoucna rozmyslel a podmínku chtěl přeformulovat (užít např. IS NULL / IS NOT NULL), nefungovalo by to, protože řádky by zahodil JOIN.

JOINY by měly následovat strukturu dat, i když v konkrétním případě to může být zbytečné.

Co se týče výkonu, tak každé rozumné SQL si na úrovni optimizéru vyhodnotí query plan v obou případech stejně (OUTER JOIN USING id+ WHERE id IS NOT NULL  je totožné jako prostý INNER JOIN USING id). Jde tedy hlavně o čitelnost a správný návyk, jak psát SQL. (id > 0 zároveň implikuje id IS NOT NULL).

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #12 kdy: 05. 10. 2019, 19:04:00 »
ale da sa aj subselect:

Ale fuj, to bude mnohem pomalejší. Na tento příklad je jediným správným řešením LEFT JOIN + WHERE.
Pro každý solidní optimizér je to jedno, výsledný query plan je stejný. Samozřejmě, ne každá databáze má solidní optimizér, takže LEFT JOIN je rozhodně jistější.

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #13 kdy: 05. 10. 2019, 19:31:26 »
No právě protože "co kdyby" je dané jako premisa (tbl2 nemusí obsahovat záznamy), je určitě lepší praxe provést OUTER JOIN a omezení dát do WHERE. Do JOINU patří definice struktury dat, do WHERE podmínky. Pokud by použil INNER JOIN, tak by část podmínky de facto přesunul do klauzule JOIN. To se nedá doporučit, SQL by mělo být čitelné a podmínky by měly být zejm. ve WHERE. Kdyby se do budoucna rozmyslel a podmínku chtěl přeformulovat (užít např. IS NULL / IS NOT NULL), nefungovalo by to, protože řádky by zahodil JOIN.
Ne, tady jde především o sémantiku. O to, jestli chce Racchek provést sémanticky INNER JOIN – tedy ve výsledné sadě nebudou záznamy, které nemají záznam v tbl2, nebo chce provést sémanticky OUTER JOIN – tedy ve výsledné sadě budou takové záznamy, které v tbl2 vůbec nejsou, nebo tam jsou a allowed mají větší než nula. Jsou to významově dva různé dotazy, dávají jinou sadu výsledků, a nejprve si tazatel musí rozhodnout, kterou sadu výsledků chce, teprve pak je možné říci, který dotaz k těm výsledkům vede.

Re:MySQL - podmíněný SELECT přes dvě tabulky
« Odpověď #14 kdy: 05. 10. 2019, 19:56:20 »
Jsou to významově dva různé dotazy, dávají jinou sadu výsledků, a nejprve si tazatel musí rozhodnout, kterou sadu výsledků chce, teprve pak je možné říci, který dotaz k těm výsledkům vede.

Nejsou, SELECT * FROM tbl1 INNER JOIN tbl2 USING (id_data) WHERE tbl2.allowed > 0
vrátí absolutně to samé jako SELECT * FROM tbl1 LEFT JOIN tbl2 USING (id_data) WHERE tbl2.allowed > 0.
To druhé je ale čistší vzhledem k zadanému popisu dat (v pravé tabulce může a nemusí být odpovídající záznam).