对于联接表中的所有缺失组合,返回0

时间:2018-11-19 06:23:52

标签: sql postgresql datetime group-by left-join

我有2个表,时间序列订单

时间序列

+------------+
|  datetime  |
+------------+
| 2018-11-01 |
| 2018-11-02 |
| 2018-11-03 |
+------------+

订单

+------------+-------------+----------+
|  datetime  | customer_id | order_id |
+------------+-------------+----------+
| 2018-11-01 |           1 |        1 |
| 2018-11-02 |           1 |        2 |
| 2018-11-03 |           2 |        3 |
+------------+-------------+----------+

我希望每天获得每个客户的订单数。

预期结果:

+------------+-------------+--------------+
|  datetime  | customer_id | number_order |
+------------+-------------+--------------+
| 2018-11-01 |           1 |            1 |
| 2018-11-02 |           1 |            1 |
| 2018-11-03 |           1 |            0 |
| 2018-11-01 |           2 |            0 |
| 2018-11-02 |           2 |            0 |
| 2018-11-03 |           2 |            1 |
+------------+-------------+--------------+

我尝试了LEFT JOIN,但并没有为所有客户返回所有时间序列

SELECT datetime, customer_id, COUNT(order_id) as number_order 
FROM timeseries
LEFT JOIN orders
ON timeseries.datetime = orders.datetime
GROUP BY datetime, customer_id
ORDER BY datetime, customer_id

>> Result

+------------+-------------+--------------+
|  datetime  | customer_id | number_order |
+------------+-------------+--------------+
| 2018-11-01 |           1 |            1 |
| 2018-11-02 |           1 |            1 |
| 2018-11-03 |           2 |            1 |
+------------+-------------+--------------+

我了解左联接只能确保返回表timeseries中的所有行,但是我需要的是表timeseries中的所有行以及每个customer_id。

感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

您需要交叉联接所有日期和所有客户,以获取日期和客户ID的所有可能组合。 然后左并加入订单:

SELECT timeseries.datetime, customers.customer_id, COUNT(orders.order_id) as number_order
FROM timeseries
CROSS JOIN (SELECT DISTINCT customer_id FROM orders) AS customers
LEFT JOIN orders ON orders.datetime = timeseries.datetime AND orders.customer_id = customers.customer_id
GROUP BY timeseries.datetime, customers.customer_id
ORDER BY timeseries.datetime, customers.customer_id

答案 1 :(得分:0)

全部使用联合然后退出联接

select t1.datetime,customer_id,COUNT(order_id) as number_order from 

(select datetime from  timeseries
union all
select datetime from orders
) t1 left join 
    orders  on t1.datetime=orders.datetime
group by  t1.datetime,customer_id