SQL查询,左侧为NULL的联接

时间:2018-10-08 16:28:30

标签: mysql sql join left-join

即使公司没有该日期的数据,我也试图按公司和日期创建小时列表。我尝试过左联接日历表并在其日期上进行分组,然后对公司进行分组,但无济于事。

SELECT cal.date, comp.name, comp.hours
FROM company AS comp
LEFT JOIN calendar AS cal ON cal.date=comp.date
GROUP BY cal.date, comp.name

当公司在该日期没有时间时,我希望得到NULL输出,例如:

2018-01-01   Company A   100
2018-01-01   Company B   NULL
2018-01-02   Company A   NULL
2018-01-02   Company B   NULL
2018-01-03   Company A   100
2018-01-03   Company B   50

但是它只返回可以找到数据的行,就像我使用了INNER JOIN一样。任何帮助,将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:0)

您可以将日历用作左侧表格,在这种情况下,您将获得所有日期

SELECT cal.date, comp.name, comp.hours
FROM calendar  AS cal  
LEFT JOIN company AS comp ON cal.date=comp.date

我没有找到任何汇总函数,所以我删除了分组依据

答案 1 :(得分:0)

您犯了3个错误,其中2个是相关的:

  1. 您在联接中交换了表的顺序(易于修复)
  2. 您的查询未反映您的意图(较难解决)
  3. 您在不需要时使用GROUP BY(在这种情况下无关紧要)

我将专注于2。您已接近目标,但并没有全部实现。修正第一个和第三个错误,这是您的查询:

SELECT cal.date, comp.name, comp.hours
FROM calendar AS cal
LEFT JOIN company AS comp ON cal.date=comp.date

这将执行以下操作:

For each cal_row in calendar:
    For each comp_row in company:
        If cal_row.date equals comp_row.date:
            Create output row and append to output
    If no rows created:
        Create output row, fill with NULLs, and append to output

因此,您的查询保证每个日期至少有1条输出行。您要查找的是每个公司每个日期的 1条输出行。一种方法是创建一个中间表,并对其进行左连接:

SELECT tbl.date, tbl.name, comp.hours
FROM (
    SELECT DISTINCT cal.date, comp.name
    FROM calendar AS cal
    CROSS JOIN company as comp
) AS tbl
LEFT JOIN LEFT JOIN company AS comp ON
    tbl.date = comp.date AND tbl.name= comp.name

http://sqlfiddle.com/#!9/517b4e/11/0

这与您所需的输出匹配。