SQL - 获取标准限制和总计数 - 是否需要子查询?

时间:2017-07-31 11:18:01

标签: sql postgresql count aggregate aggregate-functions

我正在尝试获取过去31天内订购的每位客户的订单数量,以及他们所做的总数。我想要的输出看起来像:

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 个答案:

答案 0 :(得分:2)

对整个表格进行一次传递,并使用条件聚合来计算过去31天的计数。

 //React required imports
import tinymce from './myTinymce';

class DummyEditor extends Component {

       componentwillMount(){

         window.myVars={
           tinymce:tinymce
         }

       }

       componentDidMount(){
          tinymce.init({
            //DO intializationn stuff there
          })
       }
    }

我所有的查询确实是将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 子句中的逻辑移动到过去31天的计数中。由于此新查询位于整个表中,因此原始计数现在对应于预期输出中的WHERE

答案 1 :(得分: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