SQL将行重新整理为列

时间:2013-07-15 15:02:54

标签: sql sql-server

我有一个包含以下列的表:

Name, Img1, Img2

数据的快照如下所示:

Stack, lemon.jpg, null
Stack, null, orange.jpg
Stack,plum.jpg, null
Stack,grape.jpg, aubergine.jpg

与每个名称相关联的图像数量没有限制。

但是,我想要返回前十个图像,如下所示:

select name, img1, img2, img3, img4, img5, img6 ... img10

2 个答案:

答案 0 :(得分:2)

由于表中的数据是非规范化的,我建议先解开数据,然后应用PIVOT函数将值转换回你想要的最终结果。

第一步是将img1img2列拆分为多行:

select d.name,
  c.value,
  c.col 
    + cast(row_number() over(partition by d.name 
                             order by d.name) as varchar(10)) new_col
from yourtable d
cross apply
(
  select 'img', img1 union all
  select 'img', img2
) c (col, value);

Demo。 unpivot过程会给你一个结果:

|  NAME |         VALUE | NEW_COL |
-----------------------------------
| Stack |     lemon.jpg |    img1 |
| Stack |        (null) |    img2 |
| Stack |        (null) |    img3 |
| Stack |    orange.jpg |    img4 |
| Stack |      plum.jpg |    img5 |
| Stack |        (null) |    img6 |
| Stack |     grape.jpg |    img7 |
| Stack | aubergine.jpg |    img8 |

然后,您可以将pivot功能应用于new_col中的值,该值是使用row_number()按名称分区计算的:

select name, img1, img2, img3, img4, img5,
  img6, img7, img8, img9, img10
from
(
  select d.name,
    c.value,
    c.col 
      + cast(row_number() over(partition by d.name 
                               order by d.name) as varchar(10)) new_col
  from yourtable d
  cross apply
  (
    select 'img', img1 union all
    select 'img', img2
  ) c (col, value)
) src
pivot
(
  max(value)
  for new_col in (img1, img2, img3, img4, img5,
                  img6, img7, img8, img9, img10)
) piv;

请参阅SQL Fiddle with Demo

答案 1 :(得分:1)

怎么样,

Now with working fiddle

    WITH snapshot(n, name, img1, img2) AS
(
    SELECT TOP 5
                ROW_NUMBER() OVER(ORDER BY Name) n,
                name,
                img1,
                img2
        FROM yourtable
        WHERE name = 'Stack'
        ORDER BY Name    
)
SELECT
             row1.Name,
             row1.Img1,
             row1.Img2,
             row2.Img1 Img3,
             row2.Img2 Img4,
             row3.Img1 Img5,
             row3.Img2 Img6,
             row4.Img1 Img7,
             row4.Img2 Img8,
             row5.Img1 Img9,
             row5.Img2 Img10
    FROM snapshot row1
        LEFT JOIN snapshot row2 ON row2.n = 2
        LEFT JOIN snapshot row3 ON row3.n = 3
        LEFT JOIN snapshot row4 ON row4.n = 4
        LEFT JOIN snapshot row5 ON row5.n = 5
    WHERE row1.n = 1

这可以通过定义CTE来实现,

    SELECT TOP 5
                ROW_NUMBER() OVER(ORDER BY Name) n,
                name,
                img1,
                img2
        FROM yourtable
        WHERE name = 'Stack'
        ORDER BY Name

其结果可能是

N  NAME   IMG1       IMG2 
1  Stack  lemon.jpg  (null) 
2  Stack  (null)     orange.jpg 
3  Stack  plum.jpg   (null) 
4  Stack  grape.jpg  aubergine.jpg
然后

然后选择第一行并为每个后续需要的对执行左自连接。