复杂的枢轴/非枢轴操作
Posted
技术标签:
【中文标题】复杂的枢轴/非枢轴操作【英文标题】:Complex pivot/unpivot operation 【发布时间】:2018-04-04 09:02:32 【问题描述】:我是 pivot / unpivot 及其语法的新手,我发现很难理解它。我的问题很复杂,至少对我来说是这样。
案例:我有来自不同处理器的测试数据,测试值的时间范围是 200 秒。
我的数据目前的结构如下:
TestName | Brand | Line | Model | Time | Value |
---------------------------------------------------------------
IntelTest1 | Intel | i7 | 8700k | 1 | 0.20 |
IntelTest1 | Intel | i7 | 8700k | 2 | 0.35 |
IntelTest1 | Intel | i7 | 8700k | 3 | 0.89 |
IntelTest1 | ... | ... | ... | ... | ... |
AmdTest1 | AMD | Ryzen 5 | 1600 | 1 | 0.12 |
AmdTest1 | AMD | Ryzen 5 | 1600 | 2 | 0.34 |
AmdTest1 | AMD | Ryzen 5 | 1600 | 3 | 0.51 |
AmdTest1 | ... | ... | ... | ... | ... |
... | ... | ... | ... | ... | ... |
出于报告目的,我需要将其转换为以下格式:
RowNumber | Time | IntelTest1 | AmdTest1 | ...
--------------------------------------------------
1 | | IntelTest1 | AmdTest1 |
2 | | Intel | AMD |
3 | | i7 | Ryzen 5 |
4 | | 8700k | 1600 |
5 | 1 | 0.20 | 0.12 |
6 | 2 | 0.35 | 0.34 |
7 | 3 | 0.89 | 0.51 |
8 | 4 | ... | ... |
简而言之,我首先需要每个测试的元数据(TestName、Brand、Line 和 Model),然后是每个时间点的值。列应该是每个测试名称。
我一直在尝试旋转(动态地,因为“名称”的数量是可变的)和反旋转,但我不知道如何正确构建它。
我需要多个操作来完成这个吗?
编辑:使示例更加清晰(希望如此)。
【问题讨论】:
我实际上看不出如何推导出这种转换。我可以看到你试图解释,但我担心,至少对我来说,这还不够。您可以编辑您的帖子并尝试更详细地解释转换吗?一个时间也可以有两个以上的值吗?如果是这样,会发生什么?您在示例数据中暗示您在abf
之后有更多列。如果有,它们是什么?
在演示工具(应用程序或报表生成器)中处理比在数据库中执行此操作要好得多。您在单个列中混合了多种不同数据类型的值,这并不是我们使用 SQL 的真正方式(或者,我们必须丢弃数据类型而只使用字符串 - 这就是为什么这指向表示问题而不是数据问题)
同意@Damien_The_Unbeliever 我想我理解了逻辑,但是,最后,OP 暗示他们可以在abf
之后拥有更多列的事实让我担心。特别是因为我不知道因此需要进入“标题”值的后续行。显然 Shop
和 Model
将进入第一列(abc
和 abf
),但如果有 abh
列,当 abf
的值为 'Z'
和 @987654332 时,该列中的内容@。没有进一步的分裂。
编辑了示例。这更有意义吗?
@Damien_The_Unbeliever 演示工具不够灵活,无法获得想要的结果,这就是为什么我想创建一个视图以直接将其导入工具中。不过,使用字符串数据不一定是个问题。
【参考方案1】:
您不应该使用 SQL。但如果你真的必须尝试类似下面的查询
See live demo
create table sample (TestName varchar(100),Brand varchar(100), Line varchar(100), Model varchar(100), Time int, Value decimal(5,2))
insert into sample values
('IntelTest1','Intel','i7', '8700k',1, 0.20)
,('IntelTest1','Intel','i7', '8700k',2, 0.35)
,('IntelTest1','Intel','i7', '8700k',3, 0.89)
,('AmdTest1','AMD','Ryzen 5', '1600',1, 0.12)
,('AmdTest1','AMD','Ryzen 5', '1600',2, 0.34);
select
rownumber= row_number() over ( order by (select 1)), *
from
(
select [Time]=Null ,[IntelTest1]=[1],
[Amdtest1]=[2]
from
(
select
rownum=row_number() over(order by (select 1) ) , *
from
(
select
distinct
TestName,
Brand,
Line,
Model
from sample
)s
)s
unpivot
( data for keys in (TestName, Brand, Line, Model))up
pivot
( max(data) for rownum in ([1],[2]))p
union all
select Time,[IntelTest1]=Cast([IntelTest1] as varchar(max)),[AMDTest1]=cast([AMDTest1] as varchar(max)) from
(select TestName,Time, Value from sample)s
pivot
(max(value) for TestName in ([IntelTest1],[AMDTest1]))p
)t
【讨论】:
请记住,尽管 OP 声明“动态地,因为'名称'的数量是可变的” - 所以你需要容纳一组可变的列,而不仅仅是IntelTest1
和 AMDTest1
-这使得一些非常混乱的动态 SQL 生成类似于您的示例。以上是关于复杂的枢轴/非枢轴操作的主要内容,如果未能解决你的问题,请参考以下文章