2015-07-02 42 views
0

使用連接我得到的結果是這樣如何顯示列值在SQL Server列值(只有一列列的值應顯示爲多列)

select 
     a.id, a.pname, b.childname 
    from 
     parentinfo a 
    right join 
     childinfo b on a.id = b.pid 

輸出父和子表:

id pname  childname 
    -------------------------- 
    1 Parent1  p1child1 
    1 Parent1  p1child2 
    1 Parent1  p1child3 
    2 Parent2  p2child1 
    2 Parent2  p2child2 
    3 Parent2  p3child1 
    3 Parent3  p3child2 
    3 Parent3  p3child3 
    3 Parent3  p3child4 
    4 Parent4  p4child1 
    4 Parent4  p4child2 
    4 Parent4  p4child3 

但是,孩子應該顯示爲列,一個父母應該只顯示一次。

而且可以有任意數量的孩子。

我要顯示這樣的結果:

id pname  child1 child2  child3  child4 
------------------------------------------------------ 
1 parent1 p1child1 p1child2 p1child3 
2 parent2 p2child1 p2child2 
3 parent3 p3child1 p3child2 p3child3 p3child4 
4 parent4 p4child1 p4child2 p4child3 

如何實現這一目標?使用數據透視表或其他方式?

該查詢轉換的所有行的列

DECLARE @cols AS NVARCHAR(MAX), 
     @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT ',' + QUOTENAME(childname) 
         FROM 
          (SELECT * 
          FROM parentinfo a 
          RIGHT JOIN childinfo b ON a.id = b.pid) tt 
         GROUP BY childname, id 
         ORDER BY id 
         FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'') 

    set @query = 'SELECT ' + @cols + ' from 
     (
      select value, ColumnName 
      from yourtable 
     ) x 
     pivot 
     (
      max(value) 
      for ColumnName in (' + @cols + ') 
     ) p ' 

    execute(@query) 

回答

0

下面是使用動態交叉一種方法:

SQL Fiddle

產生樣本數據

use tempdb; 
CREATE TABLE yourtable(
    id   INT, 
    pname  VARCHAR(20), 
    childname VARCHAR(20) 
) 
INSERT INTO yourtable VALUES 
(1, 'Parent1', 'p1child1'), 
(1, 'Parent1', 'p1child2'), 
(1, 'Parent1', 'p1child3'), 
(2, 'Parent2', 'p2child1'), 
(2, 'Parent2', 'p2child2'), 
(3, 'Parent3', 'p3child1'), 
(3, 'Parent3', 'p3child2'), 
(3, 'Parent3', 'p3child3'), 
(3, 'Parent3', 'p3child4'), 
(4, 'Parent4', 'p4child1'), 
(4, 'Parent4', 'p4child2'), 
(4, 'Parent4', 'p4child3'); 

動態交叉

DECLARE @maxNoChildren INT 
DECLARE @sql1 VARCHAR(4000) = '' 
DECLARE @sql2 VARCHAR(4000) = '' 
DECLARE @sql3 VARCHAR(4000) = '' 

SELECT TOP 1 @maxNoChildren = COUNT(*) FROM yourtable GROUP BY id ORDER BY COUNT(*) DESC 

SELECT @sql1 = 
'SELECT 
    id 
    ,pname 
' 

SELECT @sql2 = @sql2 + 
' ,MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(5), N) + ' THEN childname END) AS ' + QUOTENAME('child' + CONVERT(VARCHAR(5), N)) + CHAR(10) 
FROM(
    SELECT TOP(@maxNoChildren) 
     ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) 
    FROM sys.columns a 
    --CROSS JOIN sys.columns b 
)T(N) 
ORDER BY N 

SELECT @sql3 = 
'FROM(
    SELECT *, 
     RN = ROW_NUMBER() OVER(PARTITION BY id ORDER BY (SELECT NULL)) 
    FROM yourtable 
)t 
GROUP BY id, pname 
ORDER BY id' 

PRINT(@sql1 + @sql2 + @sql3) 
EXEC (@sql1 + @sql2 + @sql3) 

結果

| id | pname | child1 | child2 | child3 | child4 | 
|----|---------|----------|----------|----------|----------| 
| 1 | Parent1 | p1child1 | p1child2 | p1child3 | (null) | 
| 2 | Parent2 | p2child1 | p2child2 | (null) | (null) | 
| 3 | Parent3 | p3child1 | p3child2 | p3child3 | p3child4 | 
| 4 | Parent4 | p4child1 | p4child2 | p4child3 | (null) | 
+0

感謝您的幫助,它的偉大工程:) – Abhinav