在MySQL中的左连接并没有给我预期的结果

时间:2016-10-19 22:28:58

标签: mysql sql left-join

我有以下SQL:

SELECT t.teilnehmer_id, t.familienname, t.vorname, t.ort, t.ortsteil, t.kontrolle_ertrag, t.kontrolle_1j, t.kontrolle_brache,
     SUM(fe.nutzflaeche) AS nutzflaeche_ertrag, GROUP_CONCAT(fe.nutzflaeche) AS einzelfl_ertrag,
     SUM(fp.nutzflaeche) AS nutzflaeche_pflanzj, GROUP_CONCAT(fp.nutzflaeche) AS einzelfl_pflanzj,
     SUM(fb.nutzflaeche) AS nutzflaeche_brache, GROUP_CONCAT(fb.nutzflaeche) AS einzelfl_brache,
     SUM(fn.nutzflaeche) AS nutzflaeche_nicht_aush, GROUP_CONCAT(fn.nutzflaeche) AS einzelfl_nicht_aush
 FROM  teilnehmer t
 LEFT JOIN anrede a ON (t.anrede_id = a.anrede_id)
 LEFT JOIN antragsform af ON (t.antragsform_id = af.antragsform_id)
 LEFT JOIN bank b ON (t.bank_id = b.bank_id)
 LEFT JOIN flurverzeichnis fe ON (t.teilnehmer_id = fe.teilnehmer_id AND fe.kulturbez = 'E')
 LEFT JOIN flurverzeichnis fp ON (t.teilnehmer_id = fp.teilnehmer_id AND fp.kulturbez = 'P')
 LEFT JOIN flurverzeichnis fb ON (t.teilnehmer_id = fb.teilnehmer_id AND fb.kulturbez = 'B')
 LEFT JOIN flurverzeichnis fn ON (t.teilnehmer_id = fn.teilnehmer_id AND fn.kulturbez = 'N')
 WHERE 1 = 1
 GROUP BY t.teilnehmer_id
 ORDER BY familienname, vorname

如果在多个文化中存在匹配,则总和不会反映正确的区域。例如。如果我有5行与kulturbez' E'和2行的kulturbez' N'每个' E'行显示两次,每次显示N' N' N'行显示5次。有关如何重做SQL的建议只能用匹配的kulturbez对每一行求和一次吗? 谢谢,

1 个答案:

答案 0 :(得分:1)

如我的评论所示,不可避免的1:N连接通常需要子查询来适当地计算聚合值;但看起来您的需求可以通过条件聚合来解决,如下所示:

SELECT t.teilnehmer_id, t.familienname, t.vorname, t.ort, t.ortsteil, t.kontrolle_ertrag, t.kontrolle_1j, t.kontrolle_brache
    , SUM(CASE WHEN f.kulturbez = 'E' THEN f.nutzflaeche ELSE NULL END) AS nutzflaeche_ertrag
    , GROUP_CONCAT(CASE WHEN f.kulturbez = 'E' THEN f.nutzflaeche ELSE NULL END) AS einzelfl_ertrag
    , SUM(CASE WHEN f.kulturbez = 'P' THEN f.nutzflaeche ELSE NULL END) AS nutzflaeche_pflanzj
    , GROUP_CONCAT(CASE WHEN f.kulturbez = 'P' THEN f.nutzflaeche ELSE NULL END) AS einzelfl_pflanzj
    , SUM(CASE WHEN f.kulturbez = 'B' THEN f.nutzflaeche ELSE NULL END) AS nutzflaeche_brache
    , GROUP_CONCAT(CASE WHEN f.kulturbez = 'B' THEN f.nutzflaeche ELSE NULL END) AS einzelfl_brache
    , SUM(CASE WHEN f.kulturbez = 'N' THEN f.nutzflaeche ELSE NULL END) AS nutzflaeche_nicht_aush
    , GROUP_CONCAT(CASE WHEN f.kulturbez = 'N' THEN f.nutzflaeche ELSE NULL END) AS einzelfl_nicht_aush
FROM  teilnehmer t
    LEFT JOIN anrede a ON (t.anrede_id = a.anrede_id)
    LEFT JOIN antragsform af ON (t.antragsform_id = af.antragsform_id)
    LEFT JOIN bank b ON (t.bank_id = b.bank_id)
    LEFT JOIN flurverzeichnis f ON (t.teilnehmer_id = fe.teilnehmer_id)
WHERE 1 = 1
GROUP BY t.teilnehmer_id
ORDER BY familienname, vorname

聚合函数大部分忽略NULL值。 (另外,从技术上讲,ELSE NULL是可选的,因为如果未指定ELSE,它是假设值;但最好是明确表达您的意图。)