2015-03-02 85 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