Zobrazit příspěvky

Tato sekce Vám umožňuje zobrazit všechny příspěvky tohoto uživatele. Prosím uvědomte si, že můžete vidět příspěvky pouze z oblastí Vám přístupných.


Příspěvky - Miroslav Šilhavý

Stran: 1 ... 71 72 [73] 74 75 ... 206
1081
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 23:49:48 »
Nepochopil jsem vás špatně. Vy jste to špatně napsal. Neexistence záznamu je něco úplně jiného, než záznam, který má v jednom sloupci hodnotu NULL.

Celou tuto diskusi vedeme o podmínce, která se aplikuje na výsledek INNER / OUTER JOINU.
Celá tato diskuse je od začátku o tom, že v tbl2 nemusí existovat odpovídající záznam.
Celá tato diskuse je následně o tom, jestli se dá neexistence záznamu (reprezentovaná NULLEM ve výsledku joinu) interpretovat jako zákaz.

Domníval jsem se, že jsme oba ve stejné diskusi a že není nutné opakovat v každém postu celý kontext.
Uznávám, moje chyba.

1082
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 23:42:09 »
Zaznamenal jste, že Miroslav Šilhavý určil pro implicitní nastavení hodnotu NULL, že? Aby mohl mít záznam hodnotu allow=NULL, musí existovat. Tudíž není ho INNER JOIN připojí.

Kdyby implicitní hodnota byla reprezentovaná neexistencí záznamu, to by bylo něco jiného.

To jste mě špatně pochopil. Myšlena byla právě neexistence záznamu, která je ve výsledku joinu interpretována jako NULL. Vkládat řádek s hodnotou allow=NULL je pitomost, celý sloupec allow by bylo vhodné spíš deklarovat jako NOT NULL.

1083
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 23:18:34 »
V takovémto případě je IMHO nejlepší využít (not null) ENUM typu s hodnotami(ANO, NE, NEDEFINOVÁNO).
Ono vůbec, jak jsem psal, NULL je poměrně problematický rys SQL jazyka a je lepší se mu co to jde vyhýbat.

V praxi je problematické právě to NEDEFINOVÁNO. Znamenalo by to ke každému nedefinovanému oprávnění ukládat záznam. Např. když založíte nového uživatele, musel byste ke všem uzlům v systému přidat záznam NEDEFINOVÁNO. Proti tomu NULL vznikne na pravé straně LEFT JOINU, pokud nenajde odpovídající záznam. Proto je potřeba s ním počítat. (OUTER JOINY by ostatně nemohly ani existovat, pokud by neměly nematchující sloupce doplnit NULLY).

Osobně proti NULLŮM nic nemám. Tam, kde může být definováno NOT NULL, je to jednodušší. Ne všude to jde. Pak to chce trochu cviku na jejich výskyt nezapomenout, a už to člověku ani nepřijde jako složitost.

1084
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 20:39:48 »
S INNER JOINem samozřejmě zvládnu obsloužit i otázku 2. Už zase si pletete NULL hodnotu v datovém sloupci a neexistující záznam. To máte z toho vašeho čarování s JOINy – kdybyste se smířil s tím, že JOIN slouží ke spojení tabulek a varianta INNER nebo OUTER rozhoduje o tom, jak se bude zacházet se záznamy, které v některé tabulce neexistují, tyhle chyby byste nedělal. Neexistující záznam je něco jiného, než neexistující hodnota v záznamu, před čímž vy neustále svým OUTER JOINem zavíráte oči.

Nehovořím o datovém sloupci, ale o klíči, přes který se to spojuje. Id_data v joinované tabulce nikdy nebude NULL, kromě případu, že k joinu nedojde.

1085
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 20:00:38 »
Mít strukturu databáze, kde hodnoty >= 1 znamenají „povoleno“ a hodnoty 0 a NULL znamenají zakázáno, není dobrý nápad. Každý stav by měl být reprezentován právě jednou hodnotou.

NULL může reprezentovat implicitní nastavení (právo nebylo explicitně definované ani jako allow, ani jako disallow).
Správější by bylo tedy nikoliv "zakázáno", ale "nepovoleno".

NULL je v takovýchto případech naprosto správná hodnota, od toho je.

Můžu pak pokládat dotazy:
1. Kdo má povoleno? (allow = 1)
2. Kdo nemá povoleno? (variatněn: allow = 0 OR tbl2.id_data IS NULL nebo jen tbl2.id_data IS NULL)
3. Kdo má zakázáno? (allow = 0)

Všechny tyto tři dotazy můžete položit pouze v případě LEFT OUTER JOINU. S INNER JOINEM zvládnete obsloužit pouze otázky 1. a 3.

1086
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 19:54:14 »
Ano, přesně takto jsem to myslel. Vezmi sadu z tbl1.id_data, přičemž v tbl2.id_data musí existovat a zároveň tbl2.allowed>0

Pak je bude fungovat INNER JOIN, ale LEFT JOIN bude správnější, protože umožní obrátit výběr (selektovat záznamy, které mají allowed=0 nebo nemají odpovídající záznam v tbl2).

1087
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 13:25:50 »
Ne, ty jsi uváděl "Bydlí v Praze" a tvrdil jsi, že jediná přirozená negace je "Bydlí mimo Prahu". Což prostě v totmo případě opravdu není pravda. Když odpovím na "Bydlíš v Praze?" "Ne", tak tím nijak nevylučuji to, že jsem digitální nomád a nebydlím nikde.

Já jsem tedy vycházel z prosté úvahy. Mám sloupec "allowed" (povoleno), který může být 0 (nepovoleno) nebo >0 (povoleno). Pokud daný sloupec neexistuje (je NULL), nenaváže se, pak "povoleno" není určeno => tedy "není povoleno" = "je zakázáno".

Pokud by byl sloupec nazván "disallowed", "prohibited" či "restricted", pak bych NULL hodnotě přiřkl význam opačný => "není zakázáno" = "je povoleno".

Uznávám, že tato úvaha nemusí v praxi platit, např. pokud by se uplatňovala vícestupňová evalvace práv (pokud nenajdu oprávnění na své úrovni, podívám se o úroveň výš, výš, až nahoru) - v tom případě by měl NULL svůj význam. Ale i v tom případě OUTER JOIN poslouží líp, než INNER JOIN.

1088
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 11:56:01 »
INNER JOIN bejvá výkonnější, ale dneska si to databáze stejně zoptimalizujou.

Udělal jsem na to schválně test (na PostgreSQL). Podle očekávání ve všech třech případech si to SQL zoptimalizovalo na tutéž náročnost:

root=# EXPLAIN SELECT * FROM tbl1 LEFT JOIN tbl2 USING (id_data) WHERE allowed > 0;
                        QUERY PLAN
----------------------------------------------------------
 Nested Loop  (cost=0.00..2.07 rows=1 width=8)
   Join Filter: (tbl1.id_data = tbl2.id_data)
   ->  Seq Scan on tbl2  (cost=0.00..1.02 rows=1 width=8)
         Filter: (allowed > 0)
   ->  Seq Scan on tbl1  (cost=0.00..1.02 rows=2 width=4)
(5 rows)


root=# EXPLAIN SELECT * FROM tbl1 INNER JOIN tbl2 USING (id_data) WHERE allowed > 0;
                        QUERY PLAN
----------------------------------------------------------
 Nested Loop  (cost=0.00..2.07 rows=1 width=8)
   Join Filter: (tbl1.id_data = tbl2.id_data)
   ->  Seq Scan on tbl2  (cost=0.00..1.02 rows=1 width=8)
         Filter: (allowed > 0)
   ->  Seq Scan on tbl1  (cost=0.00..1.02 rows=2 width=4)
(5 rows)


root=# EXPLAIN SELECT * FROM tbl1 LEFT JOIN tbl2 USING (id_data) WHERE tbl2.id_data IS NOT NULL AND allowed > 0;
                        QUERY PLAN
-----------------------------------------------------------
 Nested Loop  (cost=0.00..2.07 rows=1 width=8)
   Join Filter: (tbl1.id_data = tbl2.id_data)
   ->  Seq Scan on tbl2  (cost=0.00..1.02 rows=1 width=8)
         Filter: ((id_data IS NOT NULL) AND (allowed > 0))
   ->  Seq Scan on tbl1  (cost=0.00..1.02 rows=2 width=4)
(5 rows)

1089
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 10:28:51 »
Programátoři ovšem musí psát programy podle zadání, ne podle toho, jak se jim to hodí. Když dostanou zadání „vytvoř dva dotazy, jeden s allowed = 0 a druhý s allowed > 0“, nemohou se jen tak rozhodnout, že ty dotazy nejsou programátorsky inverzní a předělat je.

To nerozporuju.

Celou dobu tvrdím, že zápis přes OUTER JOIN je univerzální vzhledem k informacím co máme, protože podmínku, ať ji vymyslíte, jak ji vymyslíte, půjde dát pouze do WHERE. Pokud použijete INNER JOIN, bude to fungovat jen v případech, které popisujete Vy.

1090
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 10:18:19 »
Logika přirozeného jazyka je jiná, než programátorská logika. Když marketingu vyjde, že lidi v Praze je potřeba oslovit jiným dárkem, než lidi ve zbytku ČR, bude chtít dvě opačné sady záznamů – obyvatele Prahy a obyvatele z jiných obcí, než je Praha. Bezdomovce, u kterých neznají adresu, opravdu řešit nebudou.

Hm, měl jsem pocit, že sem chodí spíš programátoři, než markeťáci. Pokud někdo tvoří SQL, musí se umět vyjadřovat i přijímat informace exaktně, ne jako vechtr. Možná jsem se zmýlil.

1091
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 09:02:37 »
Já jsem ale nepsal o SQL. Psal jsem o tom, jaké je obvykle zadání, jak to vnímají lidé, jak to obvykle plyne z logiky věci. Když budete mít zadání „vypište všechny uživatele, kteří bydlí v Praze“, bude k tomu obvykle inverzní zadání „vypište všechny uživatele, kteří bydlí mimo Prahu“, ne „vypište všechny uživatele, kteří bydlí mimo Prahu nebo nebydlí vůbec“. Abyste se v tom neztratil, tu podmínku jsem vám přímo slovně napsal.

Co na to říct? Opak "bydlí v Praze" je "neplatí, že bydlí v Praze", tedy "nebydlí v Praze".
Do "nebydlí v Praze" i v běžné řeči patří ti, co nebydlí nikde (např. turisté), nikoliv jen obyvatelé ostatních obcí v ČR.

Už poměrně chápu, proč jsme se ve vedlejší diskusi nemohli shodnout na výkladu zákona.

1092
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 06. 10. 2019, 04:48:54 »
O optimalizaci dotazu tady ale nikdo nemluví. Jde o sémantiku dotazu, o to, jak ho chápe vývojář.

(...)

Až na to, že normální lidi považují k dotazu „dej mi všechny záznamy, které mají podřízený záznam allowed > 0“ za inverzní „dej mi všechny záznamy, které mají podřízený záznam s alowed = 0“ (za předpokladu, že alowed > 0 a alowed = 0 jsou k sobě inverzní).

Ha! Tak jsme u podstaty věci. Pane kolego, tak toto je školácká chyba na úrovni druhé, třetí lekce práce se SQL.
Musíte s NULL počítat! (Pro začátečníky připomenu, že SELECT 1=1 navrátí TRUE, zatímco SELECT NULL=NULL nenavrátí TRUE, ale opět NULL.)

Kupř. když v tomto případě máme:
allowed > 0 znamená: přístup povolen,
allowed = 0: přístup zakázán,
allowed IS NULL: přístup neurčen,

pak SQL pak platí, že:
inverzní k"povolen" je "zakázán + neurčen",
inverzní k "zakázán" je "povolen + neurčen",
inverzní k "neurčen" je "povolen + zakázán".

Aby toto mohl vývojář opominout, musel by být sloupec allowed nastavený NOT NULL a nemohlo by platit že záznam v pravé tabulce může či nemusí existovat.

Tím bych naši diskusi uzavřel. Je zřejmé, že SQL rozumíte, doplníte si za domácí úkol studium NULL a to, jak je s ním potřeba v SQL počítat a co to znamená "sémantika".

1093
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 05. 10. 2019, 22:31:59 »
potom nepotřebujete left join

Viz výše příklad s obrácením funkce. Left join je rozhodně lepší zápis, čitelnější a vyjadřuje strukturu dat. Výsledek bude stejný, ale kdokoliv se na to podívá, pochopí líp, co od toho očekávat.

1094
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 05. 10. 2019, 22:24:41 »
...výhodou LEFT JOINU je i to, že se dá dotaz invertovat jen změnou podmíny:
SELECT * FROM tbl1 LEFT JOIN tbl2 USING (id_data) WHERE allowed > 0

a k tomu je opakem:
SELECT * FROM tbl1 LEFT JOIN tbl2 USING (id_data) WHERE allowed = 0 OR allowed IS NULL

Jak vidíte, první část se nemění, mění se pak jen podmínka. Toho s INNER JOINEM nedosáhnete.

1095
Vývoj / Re:MySQL - podmíněný SELECT přes dvě tabulky
« kdy: 05. 10. 2019, 22:13:47 »
jak jste z toho tvrzení vyvodil, že výsledek ty řádky obsahovat má?

On je obsahovat nebude. Pokud dáte WHERE tbl2.allowed > 0, tak se ty řádky vynechají.

Stran: 1 ... 71 72 [73] 74 75 ... 206