Musíte vyrovnat výsledky vašeho dotazu, abyste získali správný počet.
Řekl jste, že máte vztah jedna k mnoha z vaší tabulky souborů k jiným tabulkám
Pokud má SQL pouze klíčové slovo LOOKUP
místo toho, abyste vše nacpali do JOIN
klíčová slova, bude snadné odvodit, zda je vztah mezi tabulkou A a tabulkou B jedna ku jedné, pomocí JOIN
bude automaticky znamenat jeden k mnoha. jsem odbočil. V každém případě jsem měl již odvodit, že vaše soubory jsou proti dm_data srovnatelné; a také soubory proti kc_data jsou také jeden k mnoha. LEFT JOIN
je další nápověda, že vztah mezi první tabulkou a druhou tabulkou je jedna k mnoha; to však není definitivní, někteří kodéři prostě vše zapisují pomocí LEFT JOIN
. Na vašem LEFT JOIN ve vašem dotazu není nic špatného, ale pokud je ve vašem dotazu více tabulek one-to-many, určitě to selže, váš dotaz bude vytvářet opakující se řádky proti jiným řádkům.
from
files
left join
dm_data ON dm_data.id = files.id
left join
kc_data ON kc_data.id = files.id
Takže s tímto vědomím, že uvádíte, že jsou soubory jedna k mnoha proti dm_data, a je také proti kc_data jedna k mnoha. Můžeme dojít k závěru, že na řetězení těchto spojení a jejich seskupování do jednoho monolitického dotazu není něco v pořádku.
Příklad, pokud máte tři tabulky, jmenovitě app(files), ios_app(dm_data), android_app(kc_data), a toto jsou data například pro ios:
test=# select * from ios_app order by app_code, date_released;
ios_app_id | app_code | date_released | price
------------+----------+---------------+--------
1 | AB | 2010-01-01 | 1.0000
3 | AB | 2010-01-03 | 3.0000
4 | AB | 2010-01-04 | 4.0000
2 | TR | 2010-01-02 | 2.0000
5 | TR | 2010-01-05 | 5.0000
(5 rows)
A toto jsou data pro váš Android:
test=# select * from android_app order by app_code, date_released;
.android_app_id | app_code | date_released | price
----------------+----------+---------------+---------
1 | AB | 2010-01-06 | 6.0000
2 | AB | 2010-01-07 | 7.0000
7 | MK | 2010-01-07 | 7.0000
3 | TR | 2010-01-08 | 8.0000
4 | TR | 2010-01-09 | 9.0000
5 | TR | 2010-01-10 | 10.0000
6 | TR | 2010-01-11 | 11.0000
(7 rows)
Pokud použijete pouze tento dotaz:
select x.app_code,
count(i.date_released) as ios_release_count,
count(a.date_released) as android_release_count
from app x
left join ios_app i on i.app_code = x.app_code
left join android_app a on a.app_code = x.app_code
group by x.app_code
order by x.app_code
Místo toho bude výstup chybný:
app_code | ios_release_count | android_release_count
----------+-------------------+-----------------------
AB | 6 | 6
MK | 0 | 1
PM | 0 | 0
TR | 8 | 8
(4 rows)
Zřetězená spojení si můžete představit jako kartézský součin, takže pokud máte 3 řádky na první tabulce a 2 řádky na druhé tabulce, výstup bude 6
Zde je vizualizace, podívejte se, že existují 2 opakující se android AB pro každý ios AB. Existují 3 ios AB, takže jaký by byl počet, když uděláte COUNT(ios_app.date_released)? To bude 6; totéž s COUNT(android_app.date_released)
, toto bude také 6. Stejně tak existují 4 opakující se android TR pro každý ios TR, v ios jsou 2 TR, takže by nám to dalo 8.
.app_code | ios_release_date | android_release_date
----------+------------------+----------------------
AB | 2010-01-01 | 2010-01-06
AB | 2010-01-01 | 2010-01-07
AB | 2010-01-03 | 2010-01-06
AB | 2010-01-03 | 2010-01-07
AB | 2010-01-04 | 2010-01-06
AB | 2010-01-04 | 2010-01-07
MK | | 2010-01-07
PM | |
TR | 2010-01-02 | 2010-01-08
TR | 2010-01-02 | 2010-01-09
TR | 2010-01-02 | 2010-01-10
TR | 2010-01-02 | 2010-01-11
TR | 2010-01-05 | 2010-01-08
TR | 2010-01-05 | 2010-01-09
TR | 2010-01-05 | 2010-01-10
TR | 2010-01-05 | 2010-01-11
(16 rows)
Takže co byste měli udělat, je srovnat každý výsledek, než je připojíte k jiným tabulkám a dotazům.
Pokud vaše databáze podporuje CTE, použijte jej. Je to velmi úhledné a velmi dokumentující:
with ios_app_release_count_list as
(
select app_code, count(date_released) as ios_release_count
from ios_app
group by app_code
)
,android_release_count_list as
(
select app_code, count(date_released) as android_release_count
from android_app
group by app_code
)
select
x.app_code,
coalesce(i.ios_release_count,0) as ios_release_count,
coalesce(a.android_release_count,0) as android_release_count
from app x
left join ios_app_release_count_list i on i.app_code = x.app_code
left join android_release_count_list a on a.app_code = x.app_code
order by x.app_code;
Zatímco pokud vaše databáze ještě nemá schopnost CTE, jako je MySQL, měli byste místo toho udělat toto:
select x.app_code,
coalesce(i.ios_release_count,0) as ios_release_count,
coalesce(a.android_release_count,0) as android_release_count
from app x
left join
(
select app_code, count(date_released) as ios_release_count
from ios_app
group by app_code
) i on i.app_code = x.app_code
left join
(
select app_code, count(date_released) as android_release_count
from android_app
group by app_code
) a on a.app_code = x.app_code
order by x.app_code
Tento dotaz a dotaz ve stylu CTE zobrazí správný výstup:
app_code | ios_release_count | android_release_count
----------+-------------------+-----------------------
AB | 3 | 2
MK | 0 | 1
PM | 0 | 0
TR | 2 | 4
(4 rows)
Živý test
Nesprávný dotaz:http://www.sqlfiddle.com/#!2/9774a/ 2
Správný dotaz:http://www.sqlfiddle.com/#!2/9774a/ 1