在SQL中将行转换为列

时间:2011-07-25 09:16:40

标签: sql sql-server tsql

表A

ID  COLA    
-----------------------
A   value1      
B   value1
C   value1      

表B

ID  DETAIL_ID   COL_X   COL_Y
A   0           foo     foo
A   1           bar     bar
B   0           foo     foo

我的预期就像是

ID  COLA    COL_X_0 COL_X_1 COL_Y_0 COL_Y_1
A   value1  foo     bar     foo     bar
B   value1  foo     NULL    foo     NULL
C   value1  NULL    NULL    NULL    NULL

这意味着表B的行将是基于DETAIL_ID列的列值。

我尝试为此编写查询,但由于以下内容无法成功。 DetailID值的数量不会是fixed-length。这意味着我不能对列的名称进行硬编码。

3 个答案:

答案 0 :(得分:1)

这将给出您描述的确切输出,如果需要,您可以添加更多列

DECLARE @a table (id char, cola varchar(10))
DECLARE @b table (id char, detail_id int, colx char(3), coly char(3))

INSERT @a values('A', 'value1'),('B', 'value2'),('C','value3')
INSERT @b values('A', 0, 'foo', 'foo'),('A', 1, 'bar', 'bar'),
('B',0, 'foo','foo')--,('A', 2, 'bar', 'bar') -- add this for extra columns

CREATE TABLE ##t(id char, detail_id tinyint, colvalue char(3), col varchar(8), cola varchar(10))
DECLARE @columns varchar(max)=''
DECLARE @sqlstring varchar(1000)

;WITH a as (
SELECT a.id, a.cola, b.detail_id, colx, coly,
'col_x_' + cast(detail_id as varchar) col_a,
'col_y_' + cast(detail_id as varchar) col_b
FROM @a a LEFT JOIN @b b on a.id = b.id
) 
INSERT ##t
SELECT id, detail_id, colx, col_a, cola FROM a
UNION
SELECT id, detail_id, coly, col_b, cola FROM a
ORDER BY 4,2

SELECT @columns = coalesce(@columns, '') +',[' + col + ']'
FROM (
SELECT DISTINCT col, detail_id FROM ##t where not col is null
) a 

SET @columns = stuff(@columns, 1,1,'')

SET @sqlstring = 
'SELECT * FROM (
SELECT id, cola, col, colvalue FROM ##t 
) b
PIVOT(max(colvalue) FOR col 
in(
'+@columns+'))AS p order by 1'

EXEC(@sqlstring)

DROP TABLE ##t

答案 1 :(得分:0)

只需在B.DETAIL_ID == A.ID上连接表A和B.或者这太简单了?

答案 2 :(得分:0)

SQL查询必须指定结果集的列。这是SQL的基础。即使PIVOT要求您的查询在将列发送到RDBMS之前指定列。

由于这个原因,创建一个按行描述的列返回行的查询很困难且容易出错,并且可以根据需要调整任意数量的列。

处理动态列必须分为两个步骤。

一种选择是使两个阶段成为:

  1. 编写应用程序代码,根据数据中的不同值动态构建SQL查询。这需要额外的查询来发现存在哪些值,以便您可以构建查询。
  2. 执行SQL查询并检索结果。
  3. 另一个选择是使两个阶段成为:

    1. 运行更简单的SQL查询,将行作为行提取,因为它们存储在数据库中。
    2. 编写应用程序代码以对结果进行后处理,根据找到的值将各行中的各个值收集到一组扩展的列中。这不像第一个设计那样需要额外的查询。