按多列分组,从每组中的最后两行获取组总计数和特定列

时间:2016-04-08 22:41:04

标签: sql sql-server

我有一个SQL Server表,其中包含以下列:

Notification
===================
Id (int)
UserId (int)
Area (int)
Action (int)
ObjectId (int)
RelatedUserLink (nvarchar(100))
Created (datetime)

目标是创建一个查询,为特定用户对区域操作 ObjectId 的通知进行分组( UserId )和 返回单行,包括组的总计数以及最后两行的特定列的

每次只对一个用户( UserId )执行查询。

问题是我需要列 RelatedUserLink 用于每组的最后两个记录(基于创建)。 RelatedUserLink 对于每个组应该是不同的(如果有多个,则只应包含和计算最新的)。

每个组的结果应在一个结果行中表示。如果两个RelatedUserLink值在同一列中连接或在两列中分隔为“RelatedUserLink1”和“RelatedUserLink2”,则无关紧要。如果该组仅包含一个结果,则第二个RelatedUserLink应该为空。

期望的结果:

UserId | Area | Action | ObjectId | RelatedUserLink1 | RelatedUserLink2 | Created (latest in group) | Count 
10         1      2         100         "userlink1"       "userlink2"       2016-04-08                 20
10         1      3         200         "userlink1"       "userlink2"       2016-04-09                  4

该表将非常大,100.000-200.000行。 (相关的用户表有大约10,000行)

我也可以选择获取用户的所有通知,然后在代码中进行分组,但我希望让SQL服务器处理它有更快的方法!?

非常感谢任何帮助! 谢谢!

1 个答案:

答案 0 :(得分:1)

我会尝试使用以下WITH子句:

WITH RUL AS (
select
  UserId,
  Area,
  Action,
  ObjectId,
  RelatedUserLink as RelatedUserLink1,

  LAG(RelatedUserLink) OVER (PARTITION BY UserId, Area, Action, ObjectId ORDER BY Created) as RelatedUserLink2,

  ROW_NUMBER() OVER (PARTITION BY UserId, Area, Action, ObjectId ORDER BY Created DESC) latest_to_earliest,

  MAX(Created) OVER (PARTITION BY UserId, Area, Action, ObjectId) as Created,

  COUNT(*) OVER OVER (PARTITION BY UserId, Area, Action, ObjectId) as Count

from
  Notification
where UserId = 10
)
select 
  UserId,
  Area,
  Action,
  ObjectId,
  RelatedUserLink1,
  RelatedUserLink2,
  Created,
  Count
from 
  RUL 
where 
  latest_to_earliest = 1;

LAG函数将始终保留先前的RelatedUserLink值(除非组中只有一个值,这意味着它将是NULL)。 ROW_NUMBERCreated顺序向下计数,直至最后一行达到1。 MAXCOUNT函数保留每行上整个组的最大值和计数值,实际上与GROUP BY相同,从而无需执行单独的查询和联接。

SELECT子句之外的WITH只会为每个组选取最后一行,该行应保留RelatedUserLink中的最后一个RelatedUserLink1值和倒数第二个(或{ {1}}中的{1}}} NULL值。

相关问题