如何仅选择第一个ROW_NUMBER与SUM组合

时间:2018-06-30 16:30:16

标签: sql-server grouping row-number

我喜欢在使用SUM时按[ID]对表进行分组,还带回去 ROW_NUMBER顶部的[Product_Name]-不确定我应该使用ROW_NUMBERGROUPING SETS还是使用FETCH遍历所有内容……这是我尝试的方法:

DECLARE @SampleTable TABLE 
                     (
                          [ID] INT, 
                          [Price] MONEY, 
                          [Product_Name] VARCHAR(50)
                     )

INSERT INTO @SampleTable 
VALUES (1, 100, 'Product_1'), (1, 200, 'Product_2'),
       (1, 300, 'Product_3'), (2, 500, 'Product_4'),
       (2, 200, 'Product_5'), (2, 300, 'Product_6');

SELECT
    [ID],
    [Product_Name],
    [Price],
    SUM([Price]) OVER (PARTITION BY [ID]) AS [Price_Total],
    ROW_NUMBER() OVER (PARTITION BY [ID] ORDER BY [ID]) AS [Row_Number]
FROM
    @SampleTable T1

我想要的结果-只有两条记录:

1   Product_1   100.00   600.00     1
2   Product_4   500.00  1000.00     1

高度赞赏任何帮助或指导。

更新: 我最终使用了Prateek Sharma在他的评论中建议的内容,只是用另一个SELECT WHERE [Row_Number] = 1

包装查询
SELECT * FROM
(
    SELECT
        [ID]
        ,[Product_Name]
        ,[Price]
        ,SUM([Price]) OVER (PARTITION BY [ID]) AS [Price_Total]
        ,ROW_NUMBER() OVER (PARTITION BY [ID] ORDER BY [ID]) AS [Row_Number]
    FROM @SampleTable
) MultipleRows
WHERE [Row_Number] = 1

3 个答案:

答案 0 :(得分:1)

一种选择是使用有领带子句。没有多余的字段RN。

希望您有一个正确的序列号或日期,可以在sum() over或最后一个row_number() over中使用

示例

SELECT Top 1 with ties *
 From (
        Select [ID]
              ,[Product_Name]
              ,[Price]
              ,SUM([Price]) OVER (PARTITION BY [ID]) AS [Price_Total]
        FROM @SampleTable T1
      ) A 
Order By  ROW_NUMBER() OVER (PARTITION BY [ID] ORDER BY [Price_Total] Desc) 

返回

ID  Product_Name    Price   Price_Total
1   Product_1       100.00  600.00
2   Product_4       500.00  1000.00

答案 1 :(得分:1)

您应该有一个专栏,将在其中为ORDER BY执行ROW_NUMBER()。在这种情况下,如果只想依赖表自身索引,则可以将ID列用于ORDER BY。

因此,您的查询正确无误,就可以解决它。

其他选择是使用WITH TIES子句。但是,如果将 WITH TIES 子句与ID列上的ORDER BY一起使用,则性能将非常差。 WITH TIES仅在索引定义明确的情况下才能表现良好。并且,然后可以将该索引列与WITH TIES子句一起使用。

SELECT TOP 1 WITH TIES *
FROM (
         SELECT [ID]
               ,[Product_Name]
               ,[Price]
               ,SUM([Price]) OVER (PARTITION BY [ID]) AS [Price_Total]
         FROM @SampleTable
     ) TAB
ORDER BY ROW_NUMBER() OVER (PARTITION BY [ID] ORDER BY <IndexedColumn> DESC)

此查询可能会帮助您。但是请记住,它也不会提供比您编写的查询更好的性能。只是减少了代码行。

答案 2 :(得分:1)

除非您有定义顺序的列,否则没有“排名前ROW_NUMBER”。

如果您只想每个id任意行,则可以使用以下内容。要确定性地选择一个,您需要按照确定性的唯一标准进行排序。

DECLARE @SampleTable TABLE
(
ID             INT,
Price          MONEY,
Product_Name   VARCHAR(50),
INDEX cix CLUSTERED (ID)
);

INSERT INTO @SampleTable
VALUES      (1,100,'Product_1'),
            (1,200,'Product_2'),
            (1,300,'Product_3'),
            (2,500,'Product_4'),
            (2,200,'Product_5'),
            (2,300,'Product_6');


WITH T AS
(
SELECT *,
       OrderingColumn = ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM @SampleTable
)

SELECT ID,
       SUBSTRING(MIN(CONCAT(STR(OrderingColumn), Product_Name)), 11, 50)         AS Product_Name,
       CAST(SUBSTRING(MIN(CONCAT(STR(OrderingColumn), Price)), 11, 50) AS MONEY) AS Price,
       SUM(Price)                                                                AS Price_Total
FROM   T
GROUP  BY ID 

此计划非常有效,因为它可以使用id排序的索引,并且没有其他排序,假脱机或通过表的传递。

enter image description here