Asi to neumím napsat, abyste mě pochopil. Nemyslím strukturu dotazu, ale strukturu databáze. Ta byla popsána tak, že v tbl2 může a nemusí záznam existovat.
Já to chápu, problém vidím spíš v tom, že píšete obecně o jakési struktuře databáze, ale nenapsal jste, co konkrétně to znamená. Jak mají vypadat tabulky, jaké na nich mají být FOREIGN KEYS nebo jiná omezení?
Navíc to pokládám za nesmyslné, SELECT popisuje výsledná data, ne strukturu databáze. Může dávat smysl nad jednou dvojicí tabulek dělat INNER JOIN i OUTER JOIN, protože to má pokaždé jiný význam – i když struktura tabulek bude pořád stejná.
Jsou situace, kdy máte obecně definováno, že záznam musí existovat. Např. na dokladu uvedený odběratel (tabulka odběratelů však slouží více účelům), nebo vazba na číselníky (opět využívané z více míst). Tam je INNER JOIN na místě.
Nezapomněl jste na to, že INNER JOIN je symetrický a nerozlišuje levou a pravou tabulku? Co kdyby tazatel přeformuloval svůj požadavek na: „Chci všechny záznamy z
tbl2, které mají
allowed > 0, a k nim připojit odpovídající záznam z
tbl1. Pro každý záznam z
tbl2 existuje záznam v
tbl1.“ Struktura tabulek zůstává stejná. Výsledná sada záznamů zůstává stejná. Množiny správných SQL dotazů pro obě varianty formulace zadání jsou identické. Jenom podle vašich pravidel je najednou správně
INNER JOIN. Přitom zároveň tvrdíte, že rozhodnutí, zda
INNER nebo
OUTER JOIN závisí na struktuře tabulek, ne na sémantice dotazu (myslím toho formulovaného přirozeným jazykem, ne SQL).
Pokud tedy tazatel napsal, že v tbl2 nemusí záznam být - pak je tato skutečnost nějak významná (něco vyjadřuje).
Pokud by ta skutečnost byla významná, napsal by explicitně, jak se má zacházet s neexistujícími záznamy v
tbl2. Racchek to ale napsal jako chápavý student – sám to nepovažoval za důležité, ale uvědomil si, že se v oblasti neorientuje natolik dobře, aby to dokázal sám posoudit. Proto uvedl i tuhle informaci, o které si myslel, že je nadbytečná (proto ji neformuloval úplně přesně). Uvedl ji jen pro jistotu, kdyby to náhodou mělo vliv, aby s tím mohli znalejší lidé pracovat a upozornit ho, že na tom záleží.
Pokud tento stav zakryjete INNER JOINEM, můžete zaplakat nad výdělkem. Bohatě stačí, aby chtěl Racchek vybrat záznamy které mají allowed=0 NEBO nemají odpovídající záznam, a už je v háji a bude přepisovat nejen podmínku, ale i JOINY.
Ano, když se změní pravidla spojování, musí se přepsat
JOINy. Když bude chtít tbl1 spojit s tabulkou tbl3, bude také muset přepsat
JOIN. Výhoda je, že jsou pravidla pro spojování uvedena jinde, než podmínky, takže se to navzájem neplete.
SQL je velmi chytře navržené, ne nadarmo jsou HAVING, WHERE a ORDER BY až na konci - v nich se máte rejpat. Co je nad nimi má být co nejvíc zobecněné.
Ano, SQL je chytře navržené, proto odděluje spojovací podmínky od filtrovacích. Akorát vy se bůhvíproč snažíte spojovací podmínku nacpat do filtrovacích, i když to tazatel v původním dotazu velmi viditelně oddělil. Resp. Racchek dotaz formuloval tak, že ani nic jiného, než
INNER JOIN nepředpokládal – dokonce ani první diskutující nenapadlo, že by to mohlo být i jinak. Teprve pak se někdo začal zabývat tím dovětkem, že v
tbl2 záznamy nemusí existovat, a začal řešit, zda to je nebo není důležité. Racchek tenhle dovětek mezi podmínkami vůbec neuváděl, evidentně to tedy nevnímal jako podmínku, ale jako přirozený důsledek spojení.
Dotaz je zobecněný, pokud
JOINovací podmínky máte u
JOINu a ne ve
WHERE. Když nacpete
JOINovací podmínku do
WHERE, musíte na to myslet při každé změně
WHERE, pořád si musíte hlídat, abyste tu podmínku do
WHERE připojil správně. Dotaz je zobecněný tehdy, pokud ve
WHERE necháte opravdu jen filtrovací podmínky. Když jsem potřeboval spojit
tbl1 se záznamy z
tbl2, které mají
kategorie=1 (právě takhle bylo formulované zadání – že se spojuje s podmnožinou druhé tabulky), dal jsem i tu podmínku na
kategorie=1 do
JOINu. Aby všechny spojovací podmínky byly u
JOINu a já nemusel hlídat, že je správně přilepuju ke každému možnému
WHERE. Dokonce možná z toho
JOINu následně vznikl pohled, tím už si nejsem jistý.