SQL Server 2005,将列转换为行

7

我试图将一个表格旋转90度:将列转换为行。不允许使用PIVOT,因为PIVOT需要聚合函数。

例如,我有一个包含以下列的表:
ID int,
ISO char(2),
Text varchar(255)。

所以我有这个:

ID ISO Text
-- --- ----
 1 DE  Auto
 2 EN  Car

我想要得到如下结果:

ID EN  DE
-- --- ----
 1 Car Auto

你该如何实现呢?


3
第一张表格的第二行不应该是“1 EN Car”吗? - splattne
虽然这个问题很有趣,但我建议您描述一下最终要实现什么。我觉得您可以不用将表格变成转置的怪物就能解决您想要做的事情。 - Tiberiu Ana
1
重新阅读问题,OP试图在没有使用pivot的情况下进行透视查询。 - Kev
Kev,标题上写着SQL Server 2005。 - splattne
这不是列转行的情况,而是将多行合并成一行。 - rchacko
显示剩余4条评论
6个回答

5

这个答案是Frantisek的, 我只是复制过来纠正错误(我不能直接编辑)。

基本上,你使用那个解决方案,稍作修改:

SELECT 
    max(DE) as DE, max(EN) as EN 
FROM 
    test 
PIVOT (MAX([text]) FOR ISO in (DE,EN)) p

这将把内容放入一行中。此外,它会删除ID,因为如果您想要单行,则没有逻辑指示在合并为单行时该如何处理它。
此外,假设ISO列中的值是唯一的,否则由于MAX聚合,这将丢失数据。

2
我找到了以下解决方案:
SELECT 
    ID, DE, EN
FROM 
    TextTable 
PIVOT(MAX([text]) FOR ISO IN (DE,EN)) p

可以使用MAX聚合函数在文本上使用PIVOT。


1
select 
   t.num_claim_no,
   rtrim (xmlagg (xmlelement (e, t.txt_remarks ||'@'|| t.dat_update_date || '  ,  ')).extract ('//text()'), ',') Remarks,
   rtrim (xmlagg (xmlelement (e, t.num_update_no || ' , ')).extract ('//text()'), ',') SrlNo
from 
   gc_clm_gen_info t
   where t.txt_remarks is not null
  group by 
   t.num_claim_no
;

1
如果您尝试此解决方案并出现语法错误,请尝试通过设置数据库的兼容模式来解决。
ALTER DATABASE myDatabase SET COMPATIBILITY_LEVEL = 90;

这将把兼容性设置为SQLServer 2005,上述查询将执行而不会出现语法错误。


1

查询,即使其他答案证明您可以使用PIVOT,也不使用PIVOT :)

SELECT
    MAX(DE.Text) AS DE,
    MAX(EN.Text) AS EN  
FROM TextTable AS TT
LEFT JOIN TextTable AS DE
    ON DE.ID = TT.ID
    AND DE.ISO = 'DE'
LEFT JOIN TextTable AS EN
    ON EN.ID = TT.ID
    AND EN.ISO = 'EN'

0

既然您明确要求非枢轴解决方案:如果您知道行中将有哪些ISO,则应该可以使用此方法。我将表格称为“Test”。

declare @temp table ([ID] int, [de] varchar(255), [en] varchar(255)) -- add ISOs if necessary

INSERT @temp 
SELECT distinct [ID], '', '' from Test -- ADD '' for other ISOs if necessary

DECLARE c CURSOR read_only 
FOR SELECT [ID], [ISO], [Text] from test

DECLARE  @ID int, @ISO char(2), @Text varchar(255)
OPEN c

FETCH NEXT FROM c INTO @ID, @ISO, @Text
WHILE (@@fetch_status <> -1)
BEGIN
    IF (@@fetch_status <> -2)
    BEGIN
        UPDATE  @temp
        SET     [DE] = case when @ISO = 'DE' then @Text else [de] end,
            [EN] = case when @ISO = 'EN' then @Text else [en] end
                    -- add ISOs if necessary
        WHERE   [ID] = @ID
    END
    FETCH NEXT FROM c INTO @ID, @ISO, @Text
END

CLOSE c
DEALLOCATE c

SELECT * FROM @temp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接