我希望优化以下从历史表创建透视结果集的SQL语句。这可能已经是最具代表性的方式了,但我一直认为必须有一种更有代表性的方法。
我正在尝试优化的SQL语句
select Col1, Col2,
Max(case when TypeId = 1 then ColValue end) as Pivot1,
Max(case when TypeId = 2 then ColValue end) as Pivot2,
Max(case when TypeId = 3 then ColValue end) as Pivot3,
Max(case when TypeId = 4 then ColValue end) as Pivot4,
Max(case when TypeId = 5 then ColValue end) as Pivot5,
Max(case when TypeId = 6 then ColValue end) as Pivot6,
Max(case when TypeId = 7 then ColValue end) as Pivot7,
Max(case when TypeId = 8 then ColValue end) as Pivot8,
Max(case when TypeId = 9 then ColValue end) as Pivot9,
Max(case when TypeId = 10 then ColValue end) as Pivot10,
Max(case when TypeId = 11 then ColValue end) as Pivot11
from RowTable
group by Col1, Col2
更新:下面是表格定义
CREATE TABLE dbo.RowTable (
Id int NOT NULL,
Col1 char(8) NOT NULL,
Col2 tinyint NOT NULL,
TypeId int NOT NULL,
ColValue datetime NOT NULL,
CreatedBy varchar(50) NOT NULL,
Rowstamp timestamp NOT NULL
)
LOCK DATAROWS
GO
ALTER TABLE dbo.RowTable
ADD CONSTRAINT ukRowTable
UNIQUE (Col1, Col2, TypeId)
WITH max_rows_per_page = 0, reservepagegap = 0
答案 0 :(得分:1)
1。按表格的表现。
好吧,在任何人都可以评估该代码之前,我们需要创建表语句,包括索引。
更高级别的表现。
透视是以列的形式表示行中可用数据的功能。如果说数据库(表),标准化为3NF或5NF,这是面向行的,那么对行对象执行列函数将会很慢。与产品无关。如果您希望以速度进行列式访问(对于透视或任何其他柱状函数),则需要6NF中的数据。这也恰好使得任务所需的SQL更直接。
如果您的数据建模者准备了用于旋转的表(通常是数据仓库类型使用; Dimension-Fact结构),那么它可能不是真正的6NF,但至少它会优于5NF,并且更容易提取Pivoted值。当我看到DDL时,我将能够确定它是什么(真正的6NF;优于5NF但不是6NF)。然后我可以确定您是否使用最佳代码来获得所需内容。
当桌子不在6NF时,它只是缓慢或“昂贵”。
在此阶段,从您的代码开始,它甚至看起来不像Pivot(使用术语的标准含义),它看起来像各种值的MAX()
(调用结果列{ {1}}不会使它成为枢轴);你正在阅读每一行,一次。也就是说,你有一个程序性的思维模式,而不是一个透视或集合导向的思维模式。因此,代码很可能无法获得您需要的值(无论它是否表现良好,都是一个单独的问题)。
您对Pivotx
的使用确认了非程序集的程序方法,并且这将会很慢(创建工作表;如果您的数据很大,这将是巨大的),并且相同的信息可以是通过Dimensions获得更快的速度。为什么不为这个可旋转表使用维度表?发布与此表相关的所有Dimension表的DDL或数据模型。
我想帮助你,但有两个障碍。首先,互动之间有19天。其次,您发布的SQL不起作用:对于每一行,它在11列中返回相同的GROUP BY
; 我无法弄清楚你使用的目的。好的,ColValue
MAX()
需要超过MAX()
提交。因此,我仍然不知道你打算(不是你编码的是什么)。混淆是公平的,但在这里我们失去了意义。
是的,有更快的方法,但我需要理解意图和父表(例如,你有一个表GROUP BY
是唯一的吗?如果它是一个数据库,那么表不能表单独,他们是相关的,关系有一些目的。我意识到你不认为他们是相关的,但是这个限制产生了你发布的代码;解决方案是超越强>那个限制。
无论如何,为了避免进一步延迟,请尝试此代码。这只是猜测,对我来说不正确,因为(Col1, Col2)
是唯一的;因此,每个(Col1, Col2, TypeId)
结果行只有一组TypeId
(结果集中的列标题):
Col1, Col2
也许你可以给我反馈。
好的,现在我们有一个非标准化表。新的一套步骤。它是一个构造的结果集,使用返回Scalars的Correlated Subqueries。它不是行与列的重新排列;它不是标准的Pivot(因此提供的代码不是支点)。容易死。您可能希望更改问题标题,因为人们正在寻找真正的枢轴。是的,这将表现得更好(假设您的DDL是真实表格的真实表示)。
要明确的是,Pivot(ala MS SQL [Superceded, refer below]
函数)是一种不同的动物。我可以为Unnormalised数据库提供一个丑陋和缓慢的Pivot;或来自5NF数据库的干净但缓慢的Pivot;或来自6NF数据库的干净快速的Pivot。不是这样。
我们假设它是一个关系数据库。鉴于提供的DDL,将有一个ParentTable,其中PIVOT
是唯一的。
代码:
(Col1, Col2)
如果没有ParentTable(即它不是关系数据库),请使用SELECT Col1,
Col2,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 1 ) as Latest_1,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 2 ) as Latest_2,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 3 ) as Latest_3,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 4 ) as Latest_4,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 5 ) as Latest_5,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 6 ) as Latest_6,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 7 ) as Latest_7,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 8 ) as Latest_8,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 9 ) as Latest_9,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId=10 ) as Latest_10,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId=11 ) as Latest_11
FROM ParentTable OUTER
动态创建一个,或使用派生表:
SELECT-INTO
您可以删除RowTable中的SELECT Col1,
Col2,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 1 ) as Latest_1,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 2 ) as Latest_2,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 3 ) as Latest_3,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 4 ) as Latest_4,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 5 ) as Latest_5,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 6 ) as Latest_6,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 7 ) as Latest_7,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 8 ) as Latest_8,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId= 9 ) as Latest_9,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId=10 ) as Latest_10,
( SELECT ColValue FROM RowTable WHERE Col1=OUTER.Col1 AND Col2=OUTER.Col AND TypeId=11 ) as Latest_11
FROM (
SELECT DISTINCT
Col1,
Col2
FROM RowTable
) OUTER
列,它是一个100%冗余的列和索引,没有用处。
答案 1 :(得分:0)
透视是一项固有的昂贵操作。我不认为这可以优化。