如何选择宽SQL表的每个单元格?

时间:2017-03-23 09:59:23

标签: sql-server select

假设我在SQL中有一个 wide 表,其中有许多(比如一百多个)字段。有没有办法查询显示该表的每个单元的记录集?

来自......

Foo Bar Fizz Buzz (etc)
1   XYZ 84   J
2   ABC 29   NULL
3   KLM 73   Y

要...

Foo Bar Field Value    
1   XYZ Fizz  84
1   XYZ Buzz  J  
2   ABC Fizz  29
3   KLM Fizz  73
3   KLM Buzz  Y
(etc)

最好不必复制/粘贴一行100次,每个字段一次。

我接受,如果这是可能的,那就是'价值' field必须包含转换为字符串类型的非字符串值。

2 个答案:

答案 0 :(得分:1)

要做到这一点,你会想要使用UNPIVOT。

然而,由于Fizz,Buzz等列中的类型不同,因此它会变得有点复杂。结果列必须是单一类型,因此您需要进行一些构建

假设您的表名为“MyTable”,则代码为:

select
    unpvt.Foo,
    unpvt.Bar,
    unpvt.Field,
    unpvt.Value
from
(
    select
        Foo,
        Bar,
        CAST(Fizz as VARCHAR(3)) as Fizz,
        CAST(Buzz as VARCHAR(3)) as Buzz,
        ... <repeat for other columns>
        from
            Mytable
    ) as p unpivot(Value for Field in(
        Fizz,
        Buzz)) as unpvt

它们都已经被转换为varchar(3)的类型,但只要它是一致的(并且可能!),这可能是其他的东西。

不幸的是,您仍然需要手动将所有相关列添加到Unpivot语句中。如果要在不必键入所有列的情况下执行此操作,则需要动态SQL解决方案。请参阅此问题,了解如何实现此目标:https://dba.stackexchange.com/questions/48393/passing-column-names-dynamically-to-unpivot

答案 1 :(得分:0)

使用CROSS JOIN您还可以执行以下操作。

DECLARE @Tbl TABLE (Foo INT, Bar VARCHAR(10), Fizz INT, Buzz VARCHAR(10))
INSERT INTO @Tbl        
VALUES  
(1, 'XYZ', 84, 'J'),
(2, 'ABC', 29, NULL),
(3, 'KLM', 73, 'Y')


SELECT 
    Foo,
    Bar,
    A.Field,
    CASE WHEN A.Field = 'Fizz' THEN CAST(T.Fizz AS VARCHAR(10)) ELSE T.Buzz END Value
FROM 
    @Tbl T CROSS JOIN 
    (VALUES ('Fizz'), ('Buzz') ) A(Field)

结果:

Foo         Bar        Field Value
----------- ---------- ----- ----------
1           XYZ        Fizz  84
1           XYZ        Buzz  J
2           ABC        Fizz  29
2           ABC        Buzz  NULL
3           KLM        Fizz  73
3           KLM        Buzz  Y

如果您不想要空值,可以将两列的约束添加到WHERE条件。