2015-07-02 40 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