Sql Postgres中的左外部联接不返回Null值
下载由下载时间、下载时间id和buno id组成。 故障由故障代码、下载时间id、状态和类型组成。一次下载可能有许多错误,并且可以在下载时间id上加入 给定一组故障代码,结果必须包含每个故障代码以及相应的故障计数。如果在下载中未找到故障代码,则必须返回故障代码,且故障计数为零 这个问题似乎需要一个外部联接,但在Postgres上并没有看到像预期的那样工作,因为它似乎没有从左表返回带有null的集合 查询如下,为了简洁起见,省略了一些细节:Sql Postgres中的左外部联接不返回Null值,sql,postgresql,Sql,Postgresql,下载由下载时间、下载时间id和buno id组成。 故障由故障代码、下载时间id、状态和类型组成。一次下载可能有许多错误,并且可以在下载时间id上加入 给定一组故障代码,结果必须包含每个故障代码以及相应的故障计数。如果在下载中未找到故障代码,则必须返回故障代码,且故障计数为零 这个问题似乎需要一个外部联接,但在Postgres上并没有看到像预期的那样工作,因为它似乎没有从左表返回带有null的集合 查询如下,为了简洁起见,省略了一些细节: SELECT f.faultcode, f.downl
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子句,它在语句中使用错误代码:
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
谢谢大家的帮助!爱这个网站 这将需要一个
右侧外部连接
。右外部联接包括右表中的所有值,其中左表中没有条目的NULL
s(我不确定这是否适用于GROUP BY
,但是…如果fs_fault
是一个包含所有故障代码的表
在您的情况下,fs\u fault
似乎包含下载的所有故障。这可能是意外行为的情况吗?左侧外部联接选择第一个表中的所有内容以及第二个表中的匹配行。第一个表似乎包含下载尝试。因此,来自“from”的结果包括所有下载尝试
但是,它不一定包含所有故障代码。发生的情况是,一个或多个符合条件的代码没有故障
您需要一个包含所有故障代码的表,以使其正常工作。这里我只是创建一个故障代码列表作为第一个表。我认为以下查询可以做到这一点:
SELECT thefaults.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount
FROM (select 1000 as faultcode union all select 1100
) thefaults join
fs_fault f
on f.faultcode = thefaults.faultcode and
f.statusid in (2, 4) left outer join
download_time d
ON f.downloadtimeid = d.id
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
我承认:我正在使用SQL Server语法创建“故障”。如果您希望按故障代码计数,这似乎是最简单的解决方案:
WITH fc(faultcode) AS (VALUES (1000,1100))
SELECT fc.faultcode, count(d.downloadtimeid) as faultcount
FROM fc
LEFT JOIN (fs_fault f ON f.faultcode = fc.faultcode
AND f.statusid IN(2, 4)
JOIN download_time d ON d.id = f.downloadtimeid
AND d.bunoid = 166501
AND d.downloadtime::date BETWEEN date '2011-04-11'
AND date '2011-05-01')
GROUP BY fc.faultcode
ORDER BY fc.faultcode
请注意,我保留了您的条件,如果故障没有正确的statusid或bunoid,则不计算故障。我有点担心日期选择可能没有按照你的想法进行,所以我建议了另一种选择。如果您使用的是没有时区的时间戳,那么即使这样也可能做不到您想要的,但这是另一回事。我还添加了一个orderby
子句,因为您可能不希望结果的顺序不一致;如果没有这个子句,它可能会也可能不在分组顺序中,而且可能会在没有警告的情况下发生变化。我给出我的答案,因为我对其他答案有很大的怀疑。你必须小心过滤器的要求。记住,where子句在联接之后运行。因此,如果where子句中有任何引用非外部联接表的筛选器要求,则(在许多情况下)已使外部联接无效。因此,对于sql来说,最简单的解决方案似乎是要么使用正确的join,要么适当地移动表名,然后将筛选条件移出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_故障的过滤器要求在哪里并不重要。(无论如何,您的SQL引擎都将改变这一切)
编辑:这是一个关于join子句和where子句的筛选演示。您分析过数据吗?我怀疑这是PostgreSQL内部的问题……请提供表结构和示例数据,好吗?downloadtime d LEFT OUTER JOIN fs\u fault f ON f.downloadtime id=d.id
hasdownload\u time
作为左表,而不是fs\u fault
。联接条件与联接中的左表或右表无关。如果故障代码没有关联的下载时间,它将被where子句.Oops过滤掉。通过添加括号来强制联接的求值顺序,修复了此问题。谢谢@JayC在他的回答中就WHERE
子句与JOIN
条件提出了一个很好的观点。如前所述,如果条件排除了特定faultcode的唯一行,faultocde将不会出现。通过移动条件修复。如果faultcode没有相关的下载时间,它将被where子句过滤掉。我们假设这是提问者想要的。关于where
子句与JOIN
条件的对比,您是对的。关于这一点,我已经确定了我的答案。不过,我想你还没有回答过他的问题,即即使没有出现所需的故障代码,如何让其显示。谢谢大家:我将投票归功于所有响应者,因为我从他们身上学到了一些东西。然而,杰克,你的是最近的。唯一的更改是将“f.faultcode IN(10001100)”移动到where子句。执行此操作时,将显示正确的故障代码。谢谢,杰克!我无法让小提琴工作。我正在使用IE 7.0.5730.13CO,因为我在工作。我必须在我通常使用Chrome浏览器的家里试用。