将多行组合成一行

时间:2014-02-17 23:46:59

标签: sql sql-server tsql

我有下表

Index    BookNumber  
  2         51 
  2         52 
  2         53 
  1         41  
  1         42 
  1         43

我想提出以下输出

Index    BookNumber1  Booknumber2  Booknumber3  
----------------------------------------------
  1         41             42           43   
  2         51             52           53  

我能够提出以下查询,但输出是意外的

SELECT DISTINCT 
    index,
    CASE WHEN index = 1 THEN Booknumber END AS BookNumber1,
    CASE WHEN index = 2 THEN Booknumber END AS BookNumber2,
    CASE WHEN index = 3 THEN Booknumber END AS BookNumber3
FROM Mytable;

我得到以下输出

Index    BN1    BN2    BN3  
------------------------------
  1      41     null   null 
  1      null   42     null 
  1      null   null   43 
  2      51     null   null 
  2      null   52     null 
  2      null   null   53 

有没有办法将其压缩为仅2行?

3 个答案:

答案 0 :(得分:0)

假设每个索引的书号总是不超过3个,您可以使用:

with data as
 (select idx,
         booknumber as bn1,
         lag(booknumber, 1) over(partition by idx order by idx, booknumber) as bn2,
         lag(booknumber, 2) over(partition by idx order by idx, booknumber) as bn3
    from books)
select *
  from data
 where data.bn1 = (select max(x.bn1) from data x where x.idx = data.idx)

sqlfiddle演示在这里:http://sqlfiddle.com/#!6/8dc82/5/0

答案 1 :(得分:0)

我不太确定查询中的index如何与数据中的index列匹配。但您想要的查询是:

SELECT index,
       max(CASE WHEN index = 1 THEN Booknumber END) AS BookNumber1 ,
       max(CASE WHEN index = 2 THEN Booknumber END) AS BookNumber2,
       max(CASE WHEN index = 3 THEN Booknumber END) AS BookNumber3
FROM Mytable
GROUP BY index;

提供您的数据,查询似乎更像:

SELECT index,
       max(CASE WHEN ind = 1 THEN Booknumber END) AS BookNumber1 ,
       max(CASE WHEN ind = 2 THEN Booknumber END) AS BookNumber2,
       max(CASE WHEN ind = 3 THEN Booknumber END) AS BookNumber3
FROM (select mt.*, row_number() over (partition by index order by BookNumber) as ind
      from Mytable mt
     ) mt
GROUP BY index;

顺便说一下,“index”是一个保留字,所以我假设它只是另一个列名的占位符。否则,您需要使用双引号或方括号来转义它。

答案 2 :(得分:0)

不要忘记索引是保留字。我个人不喜欢不使用保留字作为列名,但你可以使用方括号进行补偿,如我的例子所示。

这将从sqlserver 2008 +

开始
declare @t table([Index] int, BookNumber int)
insert @t values
(2,51),(2,52),(2,53),(1,41),(1,42),(1,43)

;with cte as
(
select [Index], BookNumber, 
row_number() over (partition by [Index] order by BookNumber) rn
from @t
)
select [Index], [1] as Booknumber1, [2] as Booknumber2, [3] as Booknumber3
from cte
pivot (max([booknumber]) FOR [rn] IN ([1],[2],[3])) AS pvt 

结果:

Index Booknumber1 Booknumber2 Booknumber3
1     41          42          43
2     51          52          53