如何将前5行转移/转置到列

时间:2017-09-09 22:07:52

标签: sql-server tsql pivot pivot-table

之前我使用过Pivot,但我似乎可以让它在这个特定的数据集上工作。也许是因为我试图获得前五名的结果并同时转动。

以下是我的数据示例(请注意月份将保持不变,因为我事先这样做了):

City            # Of Accidents    Month
----            --------------    -----
Los Angeles     23                June
New York        36                June
Denver          14                June
Memphis         18                June
Orlando         25                June

我希望我的结果看起来像这样(月份,根据事故数量列出每个顶级城市的列):

Month    TopCity1    TopCity2    TopCity3      TopCity4    TopCity5
-----    --------    --------    --------      --------    --------
June     New York    Orlando     Los Angeles   Memphis     Denver

提前致谢!

3 个答案:

答案 0 :(得分:3)

另一个选项是PIVOT与Row_Number()

一致

示例

Select *
 From (
        Select Month
              ,City
              ,Col = concat('TopCity',Row_Number() over (Partition By Month Order By [# Of Accidents] Desc) )
         From  YourTable
      ) Src
 Pivot (max(City) for Col in (TopCity1,TopCity2,TopCity3,TopCity4,TopCity5) ) p

<强>返回

Month   TopCity1    TopCity2    TopCity3        TopCity4    TopCity5
June    New York    Orlando     Los Angeles     Memphis     Denver

答案 1 :(得分:2)

只是为了它的乐趣...(如果你想得到幻想)

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;

CREATE TABLE #TestData (
    City VARCHAR(20) NOT NULL,
    AccidentCount INT NOT NULL, 
    nMonth VARCHAR(10) NOT NULL 
    );
INSERT #TestData (City, AccidentCount, nMonth) VALUES 
    ('Los Angeles', 23, 'June'),
    ('New York', 36, 'June'),
    ('Denver', 14, 'June'),
    ('Memphis', 18, 'June'),
    ('Orlando', 25, 'June');

DECLARE
    @ColumnList NVARCHAR(4000),
    @sql NVARCHAR(4000),
    @DeBug BIT = 0;

WITH 
    cte_AddRN AS (
        SELECT 
            td.City, td.AccidentCount, td.nMonth,
            RN = ROW_NUMBER() OVER (PARTITION BY td.nMonth ORDER BY td.AccidentCount DESC)
        FROM
            #TestData td
        )
SELECT 
    @ColumnList = CONCAT(@ColumnList, N',
    ', QUOTENAME(ar.City), N' = MAX(CASE WHEN td.City = ', QUOTENAME(ar.City, ''''), N' THEN td.AccidentCount END)')
FROM
    cte_AddRN ar
WHERE 
    ar.RN <= 5
ORDER BY
    ar.RN;

SET @sql = CONCAT(N'
SELECT 
    td.nMonth',
    @ColumnList, N'
FROM 
    #TestData td
GROUP BY 
    td.nMonth;');

IF @DeBug = 1
BEGIN 
    PRINT(@sql);
END;
ELSE
BEGIN  
    EXEC sys.sp_executesql @sql;
END;

结果...

nMonth     New York    Orlando     Los Angeles Memphis     Denver
---------- ----------- ----------- ----------- ----------- -----------
June       36          25          23          18          14

答案 2 :(得分:1)

这可以为您提供您正在寻找的东西......

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;

CREATE TABLE #TestData (
    City VARCHAR(20) NOT NULL,
    AccidentCount INT NOT NULL, 
    nMonth VARCHAR(10) NOT NULL 
    );
INSERT #TestData (City, AccidentCount, nMonth) VALUES 
    ('Los Angeles', 23, 'June'),
    ('New York', 36, 'June'),
    ('Denver', 14, 'June'),
    ('Memphis', 18, 'June'),
    ('Orlando', 25, 'June');

WITH 
    cte_AddRN AS (
        SELECT 
            td.City, td.AccidentCount, td.nMonth,
            RN = ROW_NUMBER() OVER (PARTITION BY td.nMonth ORDER BY td.AccidentCount DESC)
        FROM
            #TestData td
        )
SELECT 
    ar.nMonth,
    TopCity1 = MAX(CASE WHEN ar.RN = 1 THEN ar.City END),
    TopCity2 = MAX(CASE WHEN ar.RN = 2 THEN ar.City END),
    TopCity3 = MAX(CASE WHEN ar.RN = 3 THEN ar.City END),
    TopCity4 = MAX(CASE WHEN ar.RN = 4 THEN ar.City END),
    TopCity5 = MAX(CASE WHEN ar.RN = 5 THEN ar.City END)
FROM
    cte_AddRN ar
GROUP BY
    ar.nMonth;

结果...

nMonth     TopCity1             TopCity2             TopCity3             TopCity4             TopCity5
---------- -------------------- -------------------- -------------------- -------------------- --------------------
June       New York             Orlando              Los Angeles          Memphis              Denver