如何在这种特定情况下显示空行?

时间:2018-01-06 10:46:41

标签: sql postgresql timestamp left-join generate-series

我正在尝试使用我在此处找到的各种示例来构建查询,但到目前为止收效甚微:

SELECT count(o.hist_create) AS daily_count, d.day AS date_column 
FROM  (
SELECT day::date FROM generate_series(
(SELECT hist_create FROM orders ORDER BY hist_create LIMIT 1),
CURRENT_TIMESTAMP, 
interval '1 day')day)d 
LEFT JOIN orders o ON date_trunc('day', o.hist_create) = d.day
WHERE o.customerId = '1234'
GROUP  BY d.day 
ORDER  BY d.day;

所以在这里我想要从特定客户的第一个订单的时间戳到今天每天计算订单,虽然这有效,但是当没有该客户的订单时它不会获取日期。我希望看到类似的内容:

number | date 
     15| 06-12-2017 
     0 | 07-12-2017
     9 | 08-12-2017
     11| 09-12-2017

但我明白了:

number | date 
     15| 06-12-2017 
     9 | 08-12-2017
     11| 09-12-2017

我认为加入会照顾到这一点,看起来这个解决方案似乎适用于其他人,但也许不是以我的方式瞄准客户时呢?

hist_create的数据类型为timestamp

2 个答案:

答案 0 :(得分:1)

问题在于您对订单表中的字段进行了过滤,这违背了使用外部联接的目的。请在您的加入中包含该条件:

SELECT count(o.hist_create) AS daily_count, d.day AS date_column 
FROM  (
SELECT day::date FROM generate_series(
(SELECT hist_create FROM orders ORDER BY hist_create LIMIT 1),
CURRENT_TIMESTAMP, 
interval '1 day')day)d 
LEFT JOIN orders o ON date_trunc('day', o.hist_create) = d.day AND o.customerId = '1234'

GROUP  BY d.day 
ORDER  BY d.day;

答案 1 :(得分:0)

@fauxmosapien指出了LEFT JOIN的主要问题。

但由于您的专栏hist_create的数据类型为timestamp,因此可以进一步改进查询:

SELECT count(o.hist_create) AS daily_count, d.day::date AS date_column 
FROM  (
   SELECT generate_series(min(hist_create), now()::timestamp, interval '1 day') AS day
   FROM   orders
   ) d
LEFT   JOIN orders o ON date_trunc('day', o.hist_create) = d.day
                    AND o.customerId = '1234'  -- why is the number quoted?
GROUP  BY d.day 
ORDER  BY d.day;

您的原始查询会生成一系列timestamptz值(因为这是CURRENT_TIMESTAMP返回的内容)强制转换为date,然后才能转回timestamp进行匹配hist_create中的LEFT JOIN

相反,请创建一个timestamp系列并直接匹配。仅转换为date输出(或以to_char()显示的任何方式格式化值)。使用EXPLAIN ANALYZE进行测试,以验证其性能稍好一些。它还通过在timestamptz和日期/时间戳之间进行投射来最小化偷偷摸摸的角落错误。更多细节: