如何对每月SQL的列中的最大值进行分组

时间:2019-03-22 09:55:46

标签: sql postgresql

我写了一个查询,向我显示月份,客户ID和每个客户花费的总金额。现在,我想显示花费最多的月份和客户。您能帮我这个忙吗,我不知道如何按月从所有客户那里获得max(money)。另外,Total_Money是通过将另外两列quantity*unitprice相乘而得到的。

我用我的代码得到了这个

------------------------------------
|  month | customer id |Total money|
------------------------------------
| April  |    12347    | value 1   |
------------------------------------
| April  |   12347     | value 2   |
------------------------------------
| April  |   12347     | value 3   |
------------------------------------

我想得到这个(每个月花钱最多的客户的ID):

----------------------------------------
|  month |  customer id  | Total money  |
----------------------------------------
| April  | id of customer|value of money|
----------------------------------------
| May    | id of customer|value of money|
----------------------------------------
| June   | id of customer|value of money|
----------------------------------------

这是我拥有的代码:

SELECT to_char(invoicedate, 'Month') as Month_Name, customerid,
       SUM((quantity*unitprice)::numeric(15, 2)) as Total_Money
FROM public."My_OnlineRetail"
GROUP BY Month_Name, customerid

4 个答案:

答案 0 :(得分:1)

Postgres支持names,因此您可以这样做:

distinct on

我应该注意SELECT DISTINCT ON (to_char(invoicedate, 'Month')) to_char(invoicedate, 'Month') as Month_Name, customerid, SUM((quantity*unitprice)::numeric(15, 2) ) as Total_Money FROM public."My_OnlineRetail" GROUP BY Month_Name, customerid ORDER BY Month_Name, Total_money DESC; 是可疑的。它不考虑年份。我更喜欢to_char(invoicedate, 'Month')

date_trunc()

答案 1 :(得分:0)

您可以从查询中创建一个CTE,然后在group之前Month_Name来获得每月最多的支出。最后,再次将此结果加入CTE中,并同时获得客户的ID:

WITH cte AS (
  SELECT 
    to_char(invoicedate, 'Month') as Month_Name, 
    customerid,
    SUM((quantity*unitprice)::numeric(15, 2)) as Total_Money
  FROM public."My_OnlineRetail"
  GROUP BY Month_Name, customerid
)

SELECT c.Month_Name, c.customerid, g.Max_Month_Money
FROM cte c INNER JOIN (
  SELECT Month_Name, MAX(Total_Money) Max_Month_Money 
  FROM cte
  GROUP BY Month_Name
) g
ON g.Month_Name = c.Month_Name AND g.Max_Month_Money = c.Total_Money

答案 2 :(得分:0)

使用with语句设置一个临时表,该表更容易从以下项中选择最终结果:

with
month_cust as (
    select
      to_char(invoicedate,'YYYY-MM') yyyymm,
      customerid,
      sum(quantity*unitprice) total_money
    from my_online_retail
    group by 
      to_char(invoicedate,'YYYY-MM'),
      customerid
)
select yyyymm, customerid, total_money
from month_cust m
where not exists (  -- where not exists a better customer that month:
         select 1 from month_cust
         where yyyymm=m.yyyymm and total_money>m.total_money
)
order by 1,2;

我还将您的to_char(invoicedate,'Month')更改为to_char(invoicedate,'YYYY-MM'),以免将所有年份的四月 加在一起。我想您希望将2018年的4月与2019年的4月分开。

答案 3 :(得分:0)

您可以按总金额的降序排列并获取第一行:

WITH "My_OnlineRetail_"( invoicedate, customerid, quantity, unitprice ) AS
(
 SELECT date'2018-04-10',12347, 50, 15 union all
 SELECT date'2018-05-13',12348, 60, 20 union all
 SELECT date'2018-06-23',12349, 55, 12  
), "My_OnlineRetail" AS
(
SELECT to_char(invoicedate, 'Month') as Month_Name, customerid,
       SUM((quantity*unitprice)::numeric(15, 2)) as Total_Money
  FROM "My_OnlineRetail_"
 GROUP BY Month_Name, customerid
)
SELECT *
  FROM "My_OnlineRetail"
 ORDER BY Total_Money desc 
 FETCH FIRST 1 ROWS ONLY;

month_name  customerid  total_money
May         12348       1200

Demo