2017-07-31 26 views
0

我试图获得在过去31天内订购的每位客户所做的订单数量以及他们制作的总数量。我期望的输出将如下所示:在SQL中获取标准限制和总数 - 是否需要子查询?

count total name   customer ID 
-------------------------------------------- 
3  10  Sarah Smith 22 
2  8  John Jenkins 15 
1  5  Delia Denton 44 

到目前为止,我有以下的,这完全适用于第一个要求:

SELECT COUNT(o.id), CONCAT(c.first_name, ' ', c.last_name) AS name, c.id AS "customer ID" 
FROM orders o 
JOIN customers c ON c.id = o.customer_id 
WHERE order_date > (CURRENT_DATE - 31) 
GROUP BY name, "customer ID" 
ORDER BY count DESC 

主要生产:

count name   customer ID 
----------------------------------- 
3  Sarah Smith 22 
2  John Jenkins 15 
1  Delia Denton 44 

但是,我有限子查询知识不会扩展到我可以如何集成一个来检索此结果集中每个客户的订单总数。 (本质上是相同的查询,但没有日期限制。)我不确定是否(或如何)将此作为过滤器以某种方式在所有订单的总套数中使用,或者是否正确的方式是将返回的ID在这里并将它们插入另一个查询中。我该怎么办?我在PostgreSQL 9.4上。

回答

2

对整个表进行一次遍历,并使用条件汇总计算最近31天的计数。

SELECT 
    COUNT(CASE WHEN order_date > (CURRENT_DATE - 31) THEN o.id END) AS cnt_31, 
    COUNT(o.id) AS total,  -- now this will count the grand total 
    CONCAT(c.first_name, ' ', c.last_name) AS name, 
    c.id AS "customer ID" 
FROM orders o 
INNER JOIN customers c 
    ON c.id = o.customer_id 
GROUP BY name, "customer ID" 
HAVING COUNT(CASE WHEN order_date > (CURRENT_DATE - 31) THEN o.id END) > 0 
ORDER BY count DESC 

我所有的查询确实是逻辑从WHERE条款移入计数的最后31天。并且由于这个新的查询遍布整个表格,原始计数现在对应于您期望的输出中的total

+0

这是完美的!我需要了解的是'CASE'。非常感谢蒂姆。 –

+2

另一种方式是'sum((order_date>(CURRENT_DATE - 31)):: integer)作为cnt_31' – Jasen

+0

@Scott我给了你一个更新来过滤零31天计数。 –

2

正如另一种方式,在这样的情况下,Postgres的版本> = 9.4, 可以使用filter条款

SELECT 
COUNT(o.id) as total_cnt, 
count(o.id) filter(WHERE order_date > (CURRENT_DATE - 31)) as last31_cnt, 
CONCAT(c.first_name, ' ', c.last_name) AS name, 
c.id AS "customer ID" 
FROM orders o 
JOIN customers c ON c.id = o.customer_id 
GROUP BY name, "customer ID" 
having count(o.id) filter(WHERE order_date > (CURRENT_DATE - 31)) > 0 
ORDER BY total_cnt DESC 
+0

这将是有趣的,它''过滤器''条款将超过我的答案+1 –

+0

'FILTER'似乎是一个有用的工具 - 感谢Oto。 –