我有一个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服务器处理它有更快的方法!?
非常感谢任何帮助! 谢谢!
答案 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_NUMBER
按Created
顺序向下计数,直至最后一行达到1。 MAX
和COUNT
函数保留每行上整个组的最大值和计数值,实际上与GROUP BY
相同,从而无需执行单独的查询和联接。
SELECT
子句之外的WITH
只会为每个组选取最后一行,该行应保留RelatedUserLink
中的最后一个RelatedUserLink1
值和倒数第二个(或{ {1}}中的{1}}} NULL
值。