选择结果到多个列

时间:2017-09-28 07:57:39

标签: sql-server tsql

不幸的是,我必须为外部应用程序提供3列格式的查询结果。

示例:

DECLARE @tmp TABLE ( id        INT
,                    somevalue VARCHAR(30) )

INSERT @tmp
VALUES ( 1, 'Text1' )
,      ( 2, 'Text2' )
,      ( 3, 'Text3' )
,      ( 4, 'Text4' )
,      ( 5, 'Text5' )
,      ( 6, 'Text6' )
,      ( 7, 'Text7' )
,      ( 8, 'Text8' )
,      (12, 'Text12')
,      (13, 'Text13')

SELECT *
FROM @tmp

但我需要这样的结果集:

|ID1 |SOMEVALUE1|ID2 |SOMEVALUE2|ID3 |SOMEVALUE3|
|1   |Text1     |2   |Text2     |3   |Text3     |
|4   |Text4     |5   |Text5     |6   |Text6     |
|7   |Text7     |8   |Text8     |12  |Text12    |
|13  |Text13    |null|null      |null|null      |

以这种方式从平面表格式化结果集的最佳方法是什么?

3 个答案:

答案 0 :(得分:3)

通过这种方式,您可以在3列上传播值

WITH
r as (
    select *, ROW_NUMBER() over (order by id) n
    from tmp
)
SELECT T1.ID ID1, T1.SOMEVALUE SOMEVALUE1, T2.ID ID2, T2.SOMEVALUE SOMEVALUE2, T3.ID ID3, T3.SOMEVALUE SOMEVALUE3
FROM r T1
LEFT JOIN r t2 ON (T2.n = T1.n+1) 
LEFT JOIN r t3 ON (T3.n = t2.n+1)
WHERE (T1.n % 3) = 1 
ORDER BY T1.id

答案 1 :(得分:2)

首先使用您的表设置一个cte,然后使用row_number列设置您的id列中的空白。我按照id排序,因为我认为这是你想要的顺序。

然后,加入该cte 3次,每个列组需要一个。第一列将有row_numbers 1,4,7等 - 基本上每个3的倍数加一。可以找到其他列,因为它们之后是一行和两行。

with cte as (
    SELECT ROW_NUMBER() over (order by id) as rowno, *
    FROM @tmp
)
select a.id ID1, a.somevalue SOMEVALUE1, b.id ID2, b.somevalue SOMEVALUE2, c.id ID3, c.somevalue SOMEVALUE3
from cte a
left join cte b on b.rowno = a.rowno + 1
left join cte c on c.rowno = a.rowno + 2
where a.rowno % 3 = 1

如果条目中没有3的完美倍数,则只会在其他列中获得空值。

答案 2 :(得分:0)

DECLARE @tmp TABLE ( id        INT
,                    somevalue VARCHAR(30) )

INSERT @tmp
VALUES ( 1, 'Text1' )
,      ( 2, 'Text2' )
,      ( 3, 'Text3' )
,      ( 4, 'Text4' )
,      ( 5, 'Text5' )
,      ( 6, 'Text6' )
,      ( 7, 'Text7' )
,      ( 8, 'Text8' )
,      ( 9, 'Text9' )

;WITH cte AS(
  SELECT *, ROW_NUMBER() OVER (ORDER BY id)%3 rn3
    FROM @tmp
),
cteR1 AS(
  SELECT c1.id, c1.somevalue, ROW_NUMBER() OVER (ORDER BY c1.id) AS rn
    FROM cte c1
    WHERE c1.rn3 = 1
),
cteR2 AS(
  SELECT c1.id, c1.somevalue, ROW_NUMBER() OVER (ORDER BY c1.id) AS rn
    FROM cte c1
    WHERE c1.rn3 = 2
),
cteR3 AS(
  SELECT c1.id, c1.somevalue, ROW_NUMBER() OVER (ORDER BY c1.id) AS rn
    FROM cte c1
    WHERE c1.rn3 = 0
)
SELECT R1.id, R1.somevalue, R2.id, R2.somevalue, R3.id, R3.somevalue
  FROM cteR1 R1
  JOIN cteR2 R2 ON R1.rn = R2.rn
  JOIN cteR3 R3 ON R1.rn = R3.rn