2015-03-02 84 views
-1

这是一个奇怪的问题,我知道它可能会更容易在SQL中不执行它,但它会让我的生活变得更容易。t-sql单列结果集为3列

基本上我有一个列结果集,我需要把它变成3列,而不是基于任何标准。

例如。

1 
2 
3 
4 
5 
6 
7 

到:

1 2 3 
4 5 6 
7 

这将永远是一个固定的3列结果,我需要在这种情况下。

目前我正在使用游标并插入表变量,这似乎有点可怕。一定会有更好的办法。

感谢

+0

结果是什么? – FlavorScape 2015-03-02 22:56:38

+0

你能解释一下这有意义吗?将数据存储在单列中开始的多列中通常是SQL“代码异味”。什么决定哪个项目进入哪个列?是否有列的顺序与列的期望顺序相匹配?为什么是3 - 未来可能是4? – ErikE 2015-03-02 23:12:39

+0

我同意它是可怕的,但它是现有系统的一个约束。 基本上我们有一些.NET代码,它会在结果集中为每行运行一次SP,并使用3个值作为SP的参数。是的,对于这个特定情况,它总是3。 – user869356 2015-03-02 23:27:17

回答

2

试试这个:

declare @t table(n int) 

insert @t(n) values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10) 

select [0],[1],[2] 
from 
(
    select n 
    , (ROW_NUMBER() over (order by n) - 1) % 3 c 
    , (ROW_NUMBER() over (order by n) - 1)/3 r 
    from @t 
) x 
pivot (max(n) for c in ([0], [1], [2])) p 
+1

完美,谢谢。 – user869356 2015-03-02 23:44:45

+0

使用此解决方案,SQL Server将对行进行两次排序。 – 2015-03-03 12:02:58

+0

同意我使用上面两次的'ROW_NUMBER()'代码片段;不过SQL在发现类似的东西时非常聪明。如果您查看为您的代码生成的查询计划,那么它完全相同;所以开发人员觉得维护/个人偏好更简单。 – JohnLBevan 2015-03-03 13:16:57

1

尽量基于PIVOT operator此解决方案:

DECLARE @MyTable TABLE (
    ID INT PRIMARY KEY 
); 
INSERT @MyTable VALUES (11) 
INSERT @MyTable VALUES (22) 
INSERT @MyTable VALUES (33) 
INSERT @MyTable VALUES (44) 
INSERT @MyTable VALUES (55) 
INSERT @MyTable VALUES (66) 
INSERT @MyTable VALUES (77); 

WITH RowsWithNum 
AS (
    SELECT *, ROW_NUMBER() OVER(ORDER BY ID) - 1 AS RowNum -- ORDER BY ID -> defines the order for numbering rows. ID values should be uniques. Thus results will be deterministic. 
    FROM @MyTable 
), Groups 
AS (
    SELECT ID, RowNum % 3 AS ColumnID, RowNum/3 AS GroupID 
    FROM RowsWithNum 
) 
SELECT * 
FROM Groups AS x 
PIVOT(MAX(x.ID) FOR x.ColumnID IN ([0], [1], [2])) AS pvt -- Comment this line to see what results return [Groups] common table expression 

结果:

GroupID 0 1 2 
------- --- ---- ---- 
0  11 22 33 
1  44 55 66 
2  77 NULL NULL 
1

这是可能的,但人是这样的丑陋的要求换货。这真的属于表示层,而不是在SQL中。

WITH original As 
(
    SELEZCT MyColumn, row_number() over (order by MyColumn) as ordinal 
    FROM RestOfOriginalQueryHere 
), 
Grouped As 
(
    SELECT MyColumn, ordinal/3 As row, ordinal % 3 As col 
    FROM original 
) 
SELECT o1.MyColumn, o2.MyColumn, o3.MyColumn 
FROM grouped g1 
LEFT JOIN grouped g2 on g2.row = g1.row and g2.col = 1 
LEFT JOIN grouped g3 on g2.row = g1.row and g3.col = 2 
WHERE g1.col = 0