SQL:在表B中可能缺少行时,连接表A和表B.

时间:2017-10-13 17:41:51

标签: mysql sql mariadb

我正在尝试从时间戳中的两个表A和B中连接数据。理想情况下,我希望tableA的每一行都满足unitCode和时间约束,如果tableB中有一个关联的行,则加入它,否则假设表B中的coloumns已连接但是为null或为空。

假设TableA看起来像这样:

id |时间戳| itemA1 | itemA2 | itemA3

和TableB看起来像这样:

id |时间戳| itemB1 | itemB2

因此数据可能如下所示:

  • 时间戳| itemA1 | itemA2 | itemA3 | itemB1 | itemB2
  • [日期时间] | 10 | 11 | 40 | 26 | 12
  • [日期时间] | 10 | 11 | 40 | 26 | 12
  • [日期时间] | 10 | 11 | 40 | null | null
  • [日期时间] | 10 | 11 | 40 | 26 | 12
  • [日期时间] | 10 | 11 | 40 | null | null

目前我正在使用它:

SELECT * FROM tableA AS a 
JOIN (SELECT * FROM tableB) AS b
ON (a.timestamp = b.timestamp)
WHERE b.unitCode = 'CODE' AND b.timestamp BETWEEN 'STARTDATETIME' AND 'ENDDATETIME' ORDER BY b.timestamp DESC`

但它只会在给定tableA的对应tableB的实例中生成行。

1 个答案:

答案 0 :(得分:5)

使用LEFT JOINLEFT JOIN获取条件语句左侧的所有记录,以及右侧适用的所有记录。但是,您需要在WHERE子句中小心,因为如果它对您的右表有一个值限制(在您的案例表'b'中),那么它仍将排除这些行。

SELECT * FROM tableA AS a 
LEFT JOIN (SELECT * FROM tableB) AS b
ON (a.timestamp = b.timestamp)
WHERE b.unitCode = 'CODE' AND b.timestamp BETWEEN 'STARTDATETIME' AND 'ENDDATETIME' ORDER BY b.timestamp DESC`

LEFT JOIN参考: https://dev.mysql.com/doc/refman/5.7/en/left-join-optimization.html

JOIN图片 enter image description here

正如@Ike指出的那样,您的查询可以更正为:

SELECT * 
FROM tableA AS a 
LEFT JOIN tableB AS b
    ON a.timestamp = b.timestamp
    AND b.unitCode = 'CODE' 
    AND b.timestamp BETWEEN 'STARTDATETIME' AND 'ENDDATETIME'
ORDER BY b.timestamp DESC`

正如我前面提到的,如果条件在WHERE子句中,它将排除LEFT JOIN的概念,因此排除NULLWHERE个值的行(因为它没有'符合表b)的标准将被排除在外。

要解决您的评论,如果您添加了LEFT JOIN条款,我建议(根据我对您的目标的理解)只有条件影响tableA并且tableB的所有条件都在{{1 }}

SELECT * 
FROM tableA AS a 
LEFT JOIN tableB AS b
    ON a.timestamp = b.timestamp
    AND b.unitCode = 'CODE' 
    AND b.timestamp BETWEEN 'STARTDATETIME' AND 'ENDDATETIME'
WHERE
    a.timestamp BETWEEN 'STARTDATETIME' AND 'ENDDATETIME'
ORDER BY b.timestamp DESC`

现在,如果你正在查找a.timestamp条件,那么LEFT JOIN中tableB的条件是多余的,因为我们已经知道tableB中的时间戳必须与表A