避免在特定列上使用GROUP BY

时间:2018-09-20 15:54:07

标签: sql sql-server group-by

我正在考虑避免在大型查询中按特定列分组,以减少性能问题。

示例:http://sqlfiddle.com/#!18/cb98e/2

CREATE TABLE [OrderTable] 
(
    [id] INT,
    [OrderGroupID] INT,
    [Total] INT,
    [fkPerson] INT,
    [fkitem] INT,

    PRIMARY KEY (id)
) 

INSERT INTO [OrderTable] (id, OrderGroupID, Total, [fkPerson], [fkItem]) 
VALUES ('1', '1', '20', '1', '1'),
       ('2', '1', '45', '2', '2'),
       ('3', '2', '32', '1', '1'),
       ('4', '2', '30', '2', '2');

CREATE TABLE [Person] 
(
    [id] INT, 
    [Name] VARCHAR(32),
    PRIMARY KEY (id)
) 

INSERT INTO [Person] (id, Name) 
VALUES ('1', 'Fred'),
       ('2', 'Sam');

CREATE TABLE [Item] 
(
    [id] INT,
    [ItemNo] VARCHAR(32),
    [Price] INT,
    PRIMARY KEY (id)
) 

INSERT INTO [Item] (id, ItemNo, Price) 
VALUES ('1', '453', '23'),
       ('2', '657', '34');

查询:

WITH TABLE1 AS 
(
    SELECT 
        P.ID AS [PersonID], 
        P.Name, 
        SUM(OT.[Total]) AS [Total], 
        i.[id] AS [ItemID],
        ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rownum,
        ot.fkperson
    FROM 
        OrderTable OT
    INNER JOIN 
        Person P ON P.ID = OT.fkperson
    INNER JOIN 
        Item I ON I.[id] = OT.[fkItem]
    GROUP BY 
        P.ID, P.Name, i.id, ot.fkperson
)
SELECT 
    *,
    Totalrows = (SELECT MAX(rownum) FROM TABLE1)
FROM 
    TABLE1

结果:

| PersonID | Name | Total | ItemID | rownum | fkperson | Totalrows |
+----------+------+-------+--------+--------+----------+-----------+
|        1 | Fred |    52 |      1 |      1 |        1 |         2 |
|        2 |  Sam |    75 |      2 |      2 |        2 |         2 |

现在,例如,如果我不想按varchar列(人员名称)分组,我可以这样做-删除人员表并稍后再加入。例如

WITH TABLE1 AS 
(
    SELECT 
        -- P.ID AS [PersonID], 
        -- P.Name, 
        SUM(OT.[Total]) AS [Total], 
        i.[id] AS [ItemID],
        ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rownum,
        ot.fkperson
    FROM 
        OrderTable OT
    -- INNER JOIN Person P ON P.ID = OT.fkperson
    INNER JOIN 
        Item I ON I.[id] = OT.[fkItem]
    GROUP BY 
        -- P.ID, P.Name,
        i.id, ot.fkperson
)
SELECT 
    p.id as [PersonID],
    p.Name,
    t1.[total],
    t1.[itemid],
    t1.[rownum],
    t1.fkperson
    -- Totalrows = (SELECT MAX(rownum) FROM TABLE1 GROUP BY
    --    i.id
    --  ,ot.fkperson        
          --   )
FROM 
    TABLE1 T1
INNER JOIN 
    Person P ON P.ID = T1.fkperson

结果:

| PersonID | Name | total | itemid | rownum | fkperson |
+----------+------+-------+--------+--------+----------+
|        1 | Fred |    52 |      1 |      1 |        1 |
|        2 |  Sam |    75 |      2 |      2 |        2 |

我的问题是我也想包括MAX(rownum)列,但是如何在上一个查询中做到这一点而又不必再次将所有内容分组?最好的方法是什么?我是否错过了一些显而易见的事情? :)

1 个答案:

答案 0 :(得分:0)

您也可以使用CROSS APPLY。并计算可以使用的总数COUNT(*) OVER()

SELECT 
    P.id as [PersonID],
    P.Name,
    T1.[total],
    I.id as [itemid],
    ROW_NUMBER() OVER (
            ORDER BY (SELECT NULL)
            ) AS [rownum],
    T1.fkperson,
    COUNT(*) OVER () Totalrows 
FROM 
    Item I
    CROSS APPLY (SELECT ot.fkperson, SUM(OT.[Total]) AS [total] 
                 FROM OrderTable OT 
                 WHERE I.[id] = OT.[fkItem] 
                 GROUP BY ot.fkperson ) AS T1
    INNER JOIN Person P ON P.id = t1.fkperson

结果:

PersonID    Name        total       itemid      rownum    fkperson    Totalrows
----------- ----------- ----------- ----------- --------- ----------- -----------
1           Fred        52          1           1         1           2
2           Sam         75          2           2         2           2