Tsql t-sql按类别分组并获取前n个值
假设我有一张桌子:Tsql t-sql按类别分组并获取前n个值,tsql,Tsql,假设我有一张桌子: Month | Person | Value ---------------------- Jan | P1 | 1 Jan | P2 | 2 Jan | P3 | 3 Feb | P1 | 5 Feb | P2 | 4 Feb | P3 | 3 Feb | P4 | 2 ... 我如何构建一个t-sql查询来获取前2个值行和第三个值行以及其他值行的总和 大概是这样的: RESULT: M
Month | Person | Value
----------------------
Jan | P1 | 1
Jan | P2 | 2
Jan | P3 | 3
Feb | P1 | 5
Feb | P2 | 4
Feb | P3 | 3
Feb | P4 | 2
...
我如何构建一个t-sql查询来获取前2个值行和第三个值行以及其他值行的总和
大概是这样的:
RESULT:
Month | Person | Value
----------------------
Jan | P3 | 3
Jan | P2 | 2
Jan | Others | 1 -(sum of the bottom value - in this case (Jan, P1, 1))
Feb | P1 | 5
Feb | P2 | 4
Feb | Others | 5 -(sum of the bottom values - in this case (Feb, P3, 3) and (Feb, P4, 2))
谢谢假设您使用的是SQL Server 2005或更高版本,那么使用CTE就可以了 将行号附加到每行,从最高值开始,每月重置。 从该查询第2行中为每个月选择前2行 SQL语句
工藤去安德烈教我一些新把戏。@Andriy:你不可能把它们都拥有。。。如果我没有弄错的话,OP需要前2个值行,我也忽略了它。人的订单应该变成价值的订单。@Lieven:看来我们都忽略了这一点。专家们……我相信你在CTE中指的是按价值排序,否则它会起作用,+1。@Andrey M:我为什么要按价值排序?好吧,这些值可以是任何东西。根据OP的需要,最终的ORDER BY可能会发生变化,因此我集中精力获取正确的数据行,使用ORDER BY只是为了提高可读性。@Andriy M:好的,我明白了,OP需要前两个值。我将更改我的帖子。安德烈的意思是行数函数中的顺序,而不是结果。
;WITH Months (Month, Person, Value) AS (
SELECT 'Jan', 'P1', 1 UNION ALL
SELECT 'Jan', 'P2', 2 UNION ALL
SELECT 'Jan', 'P3', 3 UNION ALL
SELECT 'Feb', 'P1', 5 UNION ALL
SELECT 'Feb', 'P2', 4 UNION ALL
SELECT 'Feb', 'P3', 3 UNION ALL
SELECT 'Feb', 'P4', 2
),
q AS (
SELECT Month
, Person
, Value
, RowNumber = ROW_NUMBER() OVER (PARTITION BY Month ORDER BY Value DESC)
FROM Months
)
SELECT Month
, Person
, Value
FROM (
SELECT Month
, Person
, Value
, RowNumber
FROM q
WHERE RowNumber <= 2
UNION ALL
SELECT Month
, Person = 'Others'
, SUM(Value)
, MAX(RowNumber)
FROM q
WHERE RowNumber > 2
GROUP BY
Month
) q
ORDER BY
Month DESC
, RowNumber
WITH NTable AS
(
SELECT [Month],
Person,
Value,
ROW_NUMBER() OVER (PARTITION BY [Month] ORDER BY Value DESC)
AS Rownumber
FROM MyTable
)
SELECT t.[Month],
CASE Rownumber WHEN 1 THEN t.Person WHEN 2 THEN t.Person ELSE 'Others' END As Person,
SUM(t.Value) As [Sum]
FROM NTable t
GROUP BY t.[Month], CASE Rownumber WHEN 1 THEN t.Person WHEN 2 THEN t.Person ELSE 'Others' END
ORDER BY t.[Month]
;WITH atable (Month, Person, Value) AS (
SELECT 'Jan', 'P1', 1 UNION ALL
SELECT 'Jan', 'P2', 2 UNION ALL
SELECT 'Jan', 'P3', 3 UNION ALL
SELECT 'Feb', 'P1', 5 UNION ALL
SELECT 'Feb', 'P2', 4 UNION ALL
SELECT 'Feb', 'P3', 3 UNION ALL
SELECT 'Feb', 'P4', 2
),
numbered AS (
SELECT
Month, Person, Value,
rownum = ROW_NUMBER() OVER (PARTITION BY Month ORDER BY Value DESC)
FROM atable
),
grouped AS (
SELECT
Month, Person, Value,
Grp = CASE WHEN rownum < 3 THEN rownum ELSE 3 END
FROM numbered
)
SELECT
Month,
Person = CASE Grp WHEN 3 THEN 'Others' ELSE MAX(Person) END,
Value = SUM(Value)
FROM grouped
GROUP BY Month, Grp
ORDER BY Month DESC, Grp