Autor Téma: Očakávam iný výsledok ako mám.  (Přečteno 247 krát)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 6004
  • Karma: 44
    • Verze Delphi: W10 + D11
Očakávam iný výsledok ako mám.
« kdy: 18-11-2021, 10:00:34 »
Neviem pochopiť prečo. Podľa môjho uvažovanie je SQL definované správne.
V DP mám 2 x FKOwner_Flat, ktoré nie sú v DC. Preto očakávam vo výsledku 4 záznamy. Pričom dva budú mať DC.FKOwner_Flat null. Dostávam dva záznamy, kde sú všetky FKOwner_Flat <> null. Kde mám chybu v úvahe?
Celé SQL ukazuje obrázok
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 2978
  • Karma: 108
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:Očakávam iný výsledok ako mám.
« Odpověď #1 kdy: 18-11-2021, 10:25:27 »
DC.DEPOSITPERIOD bude podle mne NULL pro ty FKOwner_Flat s NULL,  protoze ten INNER JOIN, takze ti je where odstrani, ale moc se mi nechce v tom rypat
Embarcadero MVP - Czech republic

Offline martinnr

  • Plnoletý
  • ***
  • Příspěvků: 201
  • Karma: 2
    • Verze Delphi: 7,2009,XE7
Re:Očakávam iný výsledok ako mám.
« Odpověď #2 kdy: 18-11-2021, 10:29:55 »
ak to dobre chapem, zaznamy spajas cez pole "FKOwner_Flat", ktore vsak je v 2 zaznamoch null, tak?
skus spojenie takto:
ON ( (Table1.Col1 = Table2.Col1) or (Table1.Col1 is NULL and Table2.Col1 is NULL) )

Offline martinnr

  • Plnoletý
  • ***
  • Příspěvků: 201
  • Karma: 2
    • Verze Delphi: 7,2009,XE7
Re:Očakávam iný výsledok ako mám.
« Odpověď #3 kdy: 18-11-2021, 10:32:00 »
alebo este taketo riesenia:

Use Left Outer Join instead of Inner Join to include rows with NULLS.
SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1 LEFT OUTER JOIN
    Table2 ON Table1.Col1 = Table2.Col1
    AND Table1.Col2 = Table2.Col2

Try using ISNULL function:
SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1
INNER JOIN Table2
   ON Table1.Col1 = Table2.Col1
   AND ISNULL(Table1.Col2, 'ZZZZ') = ISNULL(Table2.Col2,'ZZZZ')


ale su aj dalsie...

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 6004
  • Karma: 44
    • Verze Delphi: W10 + D11
Re:Očakávam iný výsledok ako mám.
« Odpověď #4 kdy: 18-11-2021, 11:21:42 »
Ďakujem. Vyskúšam. V skutočnosti som to samozrejme skúšal s LEFT. Tu som to dal s chybou. 1. a 2. mi nefunguje. Neviem čo v 3. znamená 'ZZZ', tak som to ani neskúšal. V takých to prípadoch si vždy najprv musím dopredu pripraviť údaje. Rád by som vedel prečo. Jeden z možných spôsobov
Kód: [Vybrat]
WITH
P AS
(SELECT DISTINCT D.FKOWNER_FLAT AS OWFP  //  Keďže sa jedná o čísla, tak je DISTINCT v pohode. Dá sa nahradiť aj pomocou GROUP BY
FROM DEPOSITS D
WHERE D.DEPOSITPERIOD = '1.5.2016' AND D.FKFOCS = 1440),
C AS
(SELECT DISTINCT D.FKOWNER_FLAT AS OWFC
FROM DEPOSITS D
WHERE D.DEPOSITPERIOD = '1.6.2016' AND D.FKFOCS = 1440) 
 
SELECT P.OWFP, C.OWFC
FROM P
  LEFT OUTER JOIN C ON (P.OWFP = C.OWFC)
Osobne som si veľmi obľúbil WITH. Z dôvodu dobrej čitateľnosti. SubQuery nie je tak čitateľný.
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 6004
  • Karma: 44
    • Verze Delphi: W10 + D11
Re:Očakávam iný výsledok ako mám.
« Odpověď #5 kdy: 18-11-2021, 11:48:44 »
Tak som to hodil priamo na FB fórum.
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 1274
  • Karma: 51
    • Verze Delphi: 10.3
Re:Očakávam iný výsledok ako mám.
« Odpověď #6 kdy: 18-11-2021, 14:36:43 »
ak to dobre chapem, zaznamy spajas cez pole "FKOwner_Flat", ktore vsak je v 2 zaznamoch null, tak?
skus spojenie takto:
ON ( (Table1.Col1 = Table2.Col1) or (Table1.Col1 is NULL and Table2.Col1 is NULL) )

Tohle se dá psát takto:
Kód: [Vybrat]
(Table2.Col1 IS NOT DISTINCT FROM Table1.Col1)

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 6004
  • Karma: 44
    • Verze Delphi: W10 + D11
Re:Očakávam iný výsledok ako mám.
« Odpověď #7 kdy: 18-11-2021, 15:52:53 »
Problém je v tom, že tu navrhnuté riešenie 1 a 2 nedávajú správny výsledok. Posledný návrh dáva úplne zmätočný výsledok. Na FB mi jeden odporúčal
Citace
NULL != '1.6.2016'
You first query filters them out by condition "DC.DEPOSITPERIOD = '1.6.2016'".
Ja vôbec netuším ako sa to dá realizovať.
Ďalší tam tvrdí
Citace
Changing LEFT JOIN to LEFT OUTER JOIN makes no difference. LEFT JOIN isthe same as LEFT OUTER JOIN; the OUTER is just noise. The problem isthat the WHERE clause references columns of DC with conditions thateliminate NULL, and therefor implicitly turns it into an inner join.
Tak som sa pozrel na vykonávací plán. Ale z neho som nič nevyčítal.
Tu je odkaz na FB [size=78%]https://groups.google.com/g/firebird-support/c/Mvy_GKQLqSo[/size]
Pribudla nová odpoveď, ktorú by som mohol aj pochopiť. A vyskúšať čo navrhuje.
« Poslední změna: 18-11-2021, 15:57:08 od Stanislav Hruška »
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 6004
  • Karma: 44
    • Verze Delphi: W10 + D11
Re:Očakávam iný výsledok ako mám.
« Odpověď #8 kdy: 18-11-2021, 16:07:39 »
Riešenie je
Kód: [Vybrat]
SELECT DP.FKOWNER_FLAT AS OWFP, DC.FKOWNER_FLAT AS OWFC
FROM DEPOSITS DP
  LEFT JOIN DEPOSITS DC ON DC.FKOWNER_FLAT = DP.FKOWNER_FLAT AND DC.DEPOSITPERIOD = '1.6.2016'
WHERE DP.DEPOSITPERIOD = '1.5.2016' AND DP.FKFOCS = 1440 AND DC.FKOWNER_FLAT IS NULL
GROUP BY DP.FKOWNER_FLAT, DC.FKOWNER_FLAT
Snáď aj pochopím prečo. Vysvetľuje to tam  :)
Je tam aj zložitejšie riešenie
Kód: [Vybrat]
SELECT DP.FKOWNER_FLAT AS OWFP, DC.FKOWNER_FLAT AS OWFC
FROM DEPOSITS DP
  LEFT JOIN
    (SELECT DEPOSITS.FKOWNER_FLAT
    FROM DEPOSITS
    WHERE DEPOSITS.DEPOSITPERIOD = '1.6.2016') DC ON DC.FKOWNER_FLAT = DP.FKOWNER_FLAT
WHERE DP.DEPOSITPERIOD = '1.5.2016' AND DP.FKFOCS = 1440 AND DC.FKOWNER_FLAT IS NULL
GROUP BY DP.FKOWNER_FLAT, DC.FKOWNER_FLAT
Bolo by pekné všetko nahradiť týmto riešením. Len neviem kde sú  :(
« Poslední změna: 18-11-2021, 16:13:00 od Stanislav Hruška »
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 6004
  • Karma: 44
    • Verze Delphi: W10 + D11
Re:Očakávam iný výsledok ako mám.
« Odpověď #9 kdy: 19-11-2021, 08:49:22 »
Vysvetlil mi to tam pekne polopate. Možno to pomôže aj niekomu inému.
Citace
Logicky je to veľmi jednoduché Stanislav. Myslite na to tak, že najskôr sa vykoná všetko JOIN a potom sa na výsledok JOIN spracuje klauzula WHERE. Iste, LEFT JOIN zahŕňa tie, ktoré nemajú zhodu na pravej strane, ale to znamená, že DC.DEPOSITPERIOD je NULL a všetky takéto záznamy sú odstránené zo sady výsledkov, pretože klauzula WHERE vyžaduje, aby to bolo 1.6.2016.
Pre mňa je dôležité to poradie vykonávania jednotlivých činností SQL. Na to som vôbec nepomyslel.
« Poslední změna: 19-11-2021, 09:14:45 od Stanislav Hruška »
W10 64b, Delphi 10.4, FireBird 3.05
Expert na kladenie nejasne formulovaných otázok.