将行值设为列值 - SQL PIVOT

时间:2012-02-02 18:36:55

标签: sql pivot

SQL从表返回以下结果:CowTracking

    ID  cow_id  barn_id
    --  ------  -------
    19    5       3
    20    5       2
    21    5       9
    22    5       1

我试图用SQL中的PIVOT获得以下结果

     cow_id  barn1  barn2  barn3  barn4
     ------  -----  -----  -----  -----
       5       3      2      9      1

这是我到目前为止的代码。

    SELECT *
    FROM 
    (
        SELECT TOP 4 *
        FROM CowTracking
            WHERE cow_id = 5
    ) AS DataTable
    PIVOT
    (
        MIN(barn_id) **IDK what function to use and which column to use it on**
        FOR ID  ??<---**NOT SURE**
        IN 
        (
        [barn1], [barn2], [barn3], [barn4]
        )
    ) AS PivotTable


    ERRORS: Error converting data type nvarchar to int
            The incorrect value "barn1" is supplied in the PIVOT operator

注意:barn_id是varchar。无法更改数据类型。

我不是想添加/乘法/聚合或其他什么。我只是想把行移到一列

我该怎么做呢? 这是正确的思考过程吗?

我甚至需要使用PIVOT吗?

1 个答案:

答案 0 :(得分:5)

由于您的表格中没有barn1..4,因此您必须以相应的ID替换barn

使用PIVOT的一个解决方案可能就像这样

SELECT  cow_id
        , [19] as [barn1]
        , [20] as [barn2]
        , [21] as [barn3]
        , [22] as [barn4]
FROM    (       
            SELECT  *
            FROM    DataTable
            PIVOT   (   MIN(barn_id)
                        FOR ID IN ([19], [20], [21], [22])
                    ) AS PivotTable
        ) q                 

使用CASEGROUP BY的其他解决方案可能是

SELECT  cow_id
        , [barn1] = SUM(CASE WHEN ID = 19 THEN barn_id END)
        , [barn2] = SUM(CASE WHEN ID = 20 THEN barn_id END)
        , [barn3] = SUM(CASE WHEN ID = 21 THEN barn_id END)
        , [barn4] = SUM(CASE WHEN ID = 22 THEN barn_id END)
FROM    DataTable
GROUP BY
        cow_id

但从本质上讲,这一切都归结为将ID硬编码为barn


修改

如果您始终返回固定数量的记录,并使用SQL Server,则可以通过

使其更加健壮。
  • 为每个结果添加ROW_NUMBER
  • 转向此前期已知号码

SQL声明

SELECT  cow_id  
        , [barn1] = SUM(CASE WHEN rn = 1 THEN barn_id END)
        , [barn2] = SUM(CASE WHEN rn = 2 THEN barn_id END)
        , [barn3] = SUM(CASE WHEN rn = 3 THEN barn_id END)
        , [barn4] = SUM(CASE WHEN rn = 4 THEN barn_id END)
FROM    (
            SELECT  cow_id
                    , rn = ROW_NUMBER() OVER (ORDER BY ID)
                    , barn_id
            FROM    DataTable       
        ) q
GROUP BY
        cow_id

测试脚本

;WITH DataTable (ID, cow_id, barn_id) AS (
    SELECT * FROM (VALUES 
        (19, 5, 3)
        , (20, 5, 2)
        , (21, 5, 9)
        , (22, 5, 1)
    ) AS q (a, b, c)        
)
SELECT  cow_id  
        , [barn1] = SUM(CASE WHEN rn = 1 THEN barn_id END)
        , [barn2] = SUM(CASE WHEN rn = 2 THEN barn_id END)
        , [barn3] = SUM(CASE WHEN rn = 3 THEN barn_id END)
        , [barn4] = SUM(CASE WHEN rn = 4 THEN barn_id END)
FROM    (
            SELECT  cow_id
                    , rn = ROW_NUMBER() OVER (ORDER BY ID)
                    , barn_id
            FROM    DataTable       
        ) q
GROUP BY
        cow_id