SQL查询 - 行到列实际上不是数据透视表

时间:2015-11-18 21:13:50

标签: sql sql-server pivot

我正在尝试将ID的某些字段移动到列中,但它似乎与我找到的所有数据透视示例不匹配。我可以找到的所有示例都使用某种形式的字段值分组。无论字段中的值如何,我都想使用更多的展示位置。我想在查询中执行此操作而不通过代码循环。

数据源示例(抱歉无法弄清楚如何在帖子上格式化表格,所以我使用了代码片段):

+----+--------+--------+
| ID | Field1 | Field2 |
+----+--------+--------+
|  1 | NULL   | NULL   |
|  2 | Jim    | 321    |
|  2 | Jack   | 54     |
|  2 | Sue    | 985    |
|  2 | Gary   | 654    |
|  3 | Herb   | 332    |
|  3 | Chevy  | 10     |
+----+--------+--------+

结果集我正在尝试生成:

+----+------+------+-------+------+------+------+
| ID | Col1 | Col2 | Col3  | Col4 | Col5 | Col6 |
+----+------+------+-------+------+------+------+
|  1 | NULL | NULL |       |      |      |      |
|  2 | Jim  | 321  | Jack  |   54 | Sue  |  985 |
|  3 | Herb | 332  | Chevy |   10 |      |      |
+----+------+------+-------+------+------+------+

2 个答案:

答案 0 :(得分:0)

SQL小提琴:http://sqlfiddle.com/#!3/a225a/1

;with cte as (
    select id
    , field1
    , field2
    , ROW_NUMBER() over (partition by id order by field1, field2) r 
    from @t   
)
select c1.id
, c1.field1 col1
, c1.field2 col2
, c2.field1 col3
, c2.field2 col4
, c3.field1 col5
, c3.field2 col6
from cte c1
left outer join cte c2 on c2.id = c1.id and c2.r = c1.r + 1
left outer join cte c3 on c3.id = c1.id and c3.r = c1.r + 2
where (c1.r % 3) = 1

<强>解释

ROW_NUMBER() over (partition by id order by field1, field2) r。此行确保每个id的列数从1开始计算。这允许我们区分多行。

CTE用于保存为c1c2c3输入相同的语句。

连接确保行中的所有项具有相同的id,并且col1,col3和col5(同样为col2,col4和col6)的数据取自连续的行。我们正在使用left outer联接,因为这些列的源表中可能没有行。

where语句表示将每组3的第一行用于c1中的数据(c2c3因此是第二和第三行每集,感谢先前的加入)。

答案 1 :(得分:0)

这是一个使用动态sql的解决方案,虽然我确信有更好的方法。小心,这有点痛苦。首先,它构建要透视和选择的列列表,构建动态sql并运行它。

DECLARE @PivotColumns as varchar(max), @SelectColumns as varchar(max), @sql as varchar(max)

SELECT @PivotColumns = ISNULL(@PivotColumns + ',', '') + ColNum,
       @SelectColumns = ISNULL(@SelectColumns + ',', '') + 'NULLIF(' + ColNum + ', ''NULL'') as ' + ColNum
from (select distinct 'Col' + cast(ROW_NUMBER() OVER (partition by id order by id) as varchar) as ColNum 
     from (select id, 
                  isnull(field1,'NULL') as field1,
                  isnull(field2,'NULL') as field2 
            from weirdpivot) cols
unpivot
(
    value
    for col in (field1, field2)
) unpivoted) DistinctColumns

set @sql = '
select id, + ' + @SelectColumns + '
from (select 
        ''Col'' + cast(ROW_NUMBER() OVER (partition by id order by id) as varchar) as colnum
        ,id
        ,value
        from (select id, 
                     isnull(field1,''NULL'') as field1,
                     isnull(field2,''NULL'') as field2 
              from weirdpivot) cols
unpivot
(
    value
    for col in (field1, field2)
) u) unpivoted
pivot
(
    max(value)
    for colnum in (' + @PivotColumns + ')
) p'

exec (@sql)