小编典典

Postgres中的左外联接不返回Null值

sql

下载由下载时间,下载时间ID和Buno ID组成。故障由故障代码,下载时间ID,状态和类型组成。下载可能有很多错误,并且可以加入下载时ID。

给定一组故障代码,结果必须包含每个故障代码以及相应的故障计数。如果在下载中未找到故障代码,则必须返回故障计数为零的故障代码。

这个问题似乎需要一个OUTER JOIN,但是在Postgres上却没有像预期的那样工作,因为它似乎没有从LEFT表中返回带有空值的集合。

该查询在下面,为简洁起见,省略了一些详细信息:

SELECT  f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM    download_time d 
LEFT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id
    AND f.faultcode IN (1000,1100)
    AND f.statusid IN(2, 4)
WHERE (d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012')
    AND d.bunoid = 166501
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode

第二天,我进行了编辑以显示答案。所有答案都很接近,并有各种帮助。但是,JayC的答案是最接近的。
这是最终的SQL,唯一的变化是WHERE子句采用了错误代码IN语句:

SELECT  f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount
FROM    download_time d  
RIGHT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id
        AND f.statusid IN(2, 4)
        AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012'
        AND d.bunoid = 166501
WHERE f.faultcode IN (1000,1100)
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode

谢谢


阅读 187

收藏
2021-03-23

共1个答案

小编典典

我之所以给出答案,是因为我对其他答案有很大的疑问。您必须注意过滤器的要求。请记住,where子句 在您加入join之后运行 。因此,如果
where子句
中有任何过滤条件要求引用非外部联接表,则您(在许多情况下)将使外部联接无效。因此,以您的sql为例,似乎最简单的解决方案是使用适当的联接或适当地移动表名称,然后将过滤条件从where子句移至join子句。

SELECT  f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM    download_time d 
RIGHT OUTER JOIN fs_fault f ON 
    f.downloadtimeid = d.id
    AND f.faultcode IN (1000,1100)
    AND f.statusid IN(2, 4)
    AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012')
    AND d.bunoid = 166501
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode

我认为应该等效的另一种方式是

SELECT  f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM    download_time d 
RIGHT OUTER JOIN fs_fault f ON 
    f.downloadtimeid = d.id
    AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012')
    AND d.bunoid = 166501
WHERE
    f.faultcode IN (1000,1100)
    AND f.statusid IN(2, 4)
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode

因为对fs_fault的过滤器要求在哪里并不严格。(并且您的SQL引擎将完全改变它)。

编辑:这是一个SQLFiddle演示对join子句和where子句的过滤。

2021-03-23