【问题标题】:Retrieve multiple information in a group by通过以下方式检索组中的多个信息
【发布时间】:2021-11-03 12:21:36
【问题描述】:

我有一个包含 3 列 Serviceid、Date、User_id 的表“购买”

一些数据如下所示:

20  2-Jan-18    40709217
20  2-Jan-18    40709217
40  2-Jan-18    40709217
40  2-Jan-20    40709217
50  2-Jan-21    40709217    
984 22-Mar-18   18246539    
269 22-Mar-18   18246539    
666 1-Apr-18    18246539

我的查询请求是:

对于每个 'user_id',获取以下信息:

  • 用户购买的前 2 个最早的 ServiceId 和日期
  • 用户最近购买的 ServiceId 和 Date
  • 用户购买的服务计数

结果表的列必须遵循以下顺序: User_id、FirstServiceid、SecondServiceid、FirstServiceDate、SecondServiceDate、LastServiceid、LastServiceDate、TotalService。

预期输出:

User_id FirstServiceid SecondServiceid FirstDate SecondDate LastServiceid LastDate TotalServices
40709217 20 40 2-Jan-18 2-Jan-20 50 2-Jan-21 5
18246539 984 666 22-Mar-18 1-Apr-18 666 1-Apr-18 3

我的想法是进行聚合,然后将它们连接在一起,但我遇到了这个错误

“列 'purchase.Serviceid' 在选择列表中无效,因为它 不包含在聚合函数或 GROUP BY 中 条款”

调用最新的Serviceid和Date时:

select user_id, max(date), serviceid    
from purchases    
group by user_id

如何克服这个问题,有没有更好的方法来聚合大量信息而无需使用 JOIN?

【问题讨论】:

  • 您可以从示例中的输入值中添加预期的输出值吗?
  • @Magnus 我编辑了!
  • 为什么 SecondServiceid 是 40 而不是 20?你想要不同的 SecondServiceid 吗?
  • 您使用的是哪个数据库管理系统(例如mysql/sqlserver/postgres等)以及什么版本?
  • @AnkitBajpai 因为用户 40709217 购买东西的第二个日期是 2-Jan-20,而那是 Serviceid 40!

标签: sql


【解决方案1】:

您可以尝试使用以下使用窗口函数(例如 row_numberdense_rank)在通过 user_id 聚合结果之前识别所需的记录,并在 MAX 函数中使用 case 表达式来提取数据所需的列

SELECT
    User_id,
    MAX(CASE WHEN earliest_order=1 and rp=1 THEN Serviceid END) as FirstServiceid,
    MAX(CASE WHEN earliest_order=2 and rp=1 THEN Serviceid END) as SecondServiceid,
    MAX(CASE WHEN earliest_order=1 and rp=1 THEN [Date] END) as FirstServiceDate,
    MAX(CASE WHEN earliest_order=2 and rp=1 THEN [Date] END) as SecondServiceDate,
    MAX(CASE WHEN latest_order=1 THEN Serviceid END) as LastServiceid,
    MAX(CASE WHEN latest_order=1 THEN [Date] END) as LastServiceDate,
    COUNT(1) as TotalService
FROM (
   SELECT 
       *,
       DENSE_RANK() OVER (
           PARTITION BY User_id
           ORDER BY [Date] 
       ) as earliest_order,
       ROW_NUMBER() OVER (
           PARTITION BY User_id
           ORDER BY [Date] DESC, Serviceid
       ) as latest_order,
       ROW_NUMBER() OVER (
              PARTITION BY User_id,[Date]
              ORDER BY Serviceid DESC
       ) rp
   FROM 
       purchases
   
) t
GROUP BY
    User_id
ORDER BY
    User_id DESC

上面使用的子查询的结果也包含在下面,供您阅读。

   SELECT
        *,
       DENSE_RANK() OVER (
           PARTITION BY User_id
           ORDER BY [Date] 
       ) as earliest_order,
       ROW_NUMBER() OVER (
           PARTITION BY User_id
           ORDER BY [Date] DESC, Serviceid
       ) as latest_order,
       ROW_NUMBER() OVER (
              PARTITION BY User_id,[Date]
              ORDER BY Serviceid DESC
       ) rank_priority
   FROM
           purchases
    ORDER BY User_id, [Date], Serviceid DESC
Serviceid Date User_id earliest_order latest_order rank_priority
984 2018-03-22 18246539 1 3 1
269 2018-03-22 18246539 1 2 2
666 2018-04-01 18246539 2 1 1
40 2018-01-02 40709217 1 5 1
20 2018-01-02 40709217 1 3 2
20 2018-01-02 40709217 1 4 3
40 2020-01-02 40709217 2 2 1
50 2021-01-02 40709217 3 1 1

View working demo db fiddle here

【讨论】:

  • 对于像我这样刚接触 SQL 的人来说,这需要涵盖很多内容。谢谢!
猜你喜欢
  • 2011-12-01
  • 2019-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多