假设我在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必须包含转换为字符串类型的非字符串值。
答案 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条件。