在这种特定情况下如何显示空行?
How to display empty rows in this specific case?
我正在尝试使用我在此处找到的各种示例来构建查询,但到目前为止收效甚微:
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
。
问题是您在订单 table 的字段上进行过滤,这违背了使用外部联接的目的。改为在您的加入中包含该条件:
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;
@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
returns)在必须转换回 [=13 之前转换为 date
=] 匹配 LEFT JOIN
.
中的 hist_create
相反,创建一个 timestamp
系列并直接匹配。仅转换为 date
用于输出(或以任何您喜欢的方式格式化值以使用 to_char()
显示)。使用 EXPLAIN ANALYZE
进行测试以验证其性能是否稍好。它还通过在 timestamptz 和日期/时间戳之间进行转换来最大程度地减少偷偷摸摸的角落案例错误。更多详情:
- Generating time series between two dates in PostgreSQL
我正在尝试使用我在此处找到的各种示例来构建查询,但到目前为止收效甚微:
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
。
问题是您在订单 table 的字段上进行过滤,这违背了使用外部联接的目的。改为在您的加入中包含该条件:
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;
@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
returns)在必须转换回 [=13 之前转换为 date
=] 匹配 LEFT JOIN
.
hist_create
相反,创建一个 timestamp
系列并直接匹配。仅转换为 date
用于输出(或以任何您喜欢的方式格式化值以使用 to_char()
显示)。使用 EXPLAIN ANALYZE
进行测试以验证其性能是否稍好。它还通过在 timestamptz 和日期/时间戳之间进行转换来最大程度地减少偷偷摸摸的角落案例错误。更多详情:
- Generating time series between two dates in PostgreSQL