在Sybase Ase中优化用于透视表的SQL的最佳方法

时间:2010-11-24 21:38:47

标签: sql sybase-ase

我希望优化以下从历史表创建透视结果集的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

2 个答案:

答案 0 :(得分:1)

对原始问题的回应

1。按表格的表现。
好吧,在任何人都可以评估该代码之前,我们需要创建表语句,包括索引。

  1. 更高级别的表现。
    透视是以列的形式表示行中可用数据的功能。如果说数据库(表),标准化为3NF或5NF,这是面向行的,那么对行对象执行列函数将会很慢。与产品无关。如果您希望以速度进行列式访问(对于透视或任何其他柱状函数),则需要6NF中的数据。这也恰好使得任务所需的SQL更直接。

    如果您的数据建模者准备了用于旋转的表(通常是数据仓库类型使用; Dimension-Fact结构),那么它可能不是真正的6NF,但至少它会优于5NF,并且更容易提取Pivoted值。当我看到DDL时,我将能够确定它是什么(真正的6NF;优于5NF但不是6NF)。然后我可以确定您是否使用最佳代码来获得所需内容。

    当桌子不在6NF时,它只是缓慢或“昂贵”。

  2. 在此阶段,从您的代码开始,它甚至看起来不像Pivot(使用术语的标准含义),它看起来像各种值的MAX()(调用结果列{ {1}}不会使它成为枢轴);你正在阅读每一行,一次。也就是说,你有一个程序性的思维模式,而不是一个透视或集合导向的思维模式。因此,代码很可能无法获得您需要的值(无论它是否表现良好,都是一个单独的问题)。

    您对Pivotx的使用确认了非程序集的程序方法,并且这将会很慢(创建工作表;如果您的数据很大,这将是巨大的),并且相同的信息可以是通过Dimensions获得更快的速度。为什么不为这个可旋转表使用维度表?发布与此表相关的所有Dimension表的DDL或数据模型。

  3. 对评论的回应

    我想帮助你,但有两个障碍。首先,互动之间有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。不是这样。

    1. 我们假设它是一个关系数据库。鉴于提供的DDL,将有一个ParentTable,其中PIVOT是唯一的。

    2. 代码:

      (Col1, Col2)

    3. 如果没有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

    4. 您可以删除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)

透视是一项固有的昂贵操作。我不认为这可以优化。