2017-10-11 30 views
1

我想我正在尝试做一些无法完成的事情。我正在尝试创建一个数据透视表,同时通过聚合两个不同的列来完成两个支点。我创建了一个非常简单的示例,以使这一点更易于理解。创建数据透视表与聚合无需加入

CREATE TABLE two_aggregate_pivot (
    ID INT, 
    category CHAR(1), 
    value INT 
) 

INSERT INTO dbo.two_aggregate_pivot 
    (ID, category, value) 
VALUES (1, 'A', 100), 
     (1, 'B', 97), 
     (1, 'D', NULL), 
     (2, 'A', 86), 
     (2, 'C', 83), 
     (2, 'D', 81)    

我可以透视得到类别的数量如下:

SELECT piv1.ID, 
     [A] AS cat_A, 
     [B] AS cat_B, 
     [C] AS cat_C, 
     [D] AS cat_D 
FROM 
(SELECT ID, category FROM dbo.two_aggregate_pivot) SRC 
PIVOT 
(
    COUNT(category) 
    FOR category IN ([A],[B],[C],[D]) 
) piv1 

而且我得到了我想要的东西。

ID cat_A cat_B cat_C cat_D 
1 1  1  0  1 
2 1  0  1  1 

也是如此,我可以写一个完全独立的查询,从MAX(值)添加源选择值列,而不是总量,并获得最大价值的支点。

ID val_A val_B val_C val_D 
1 100  97  NULL NULL 
2 86  NULL 83  81 

但我无法弄清楚是如何让他们两个。

ID cat_A cat_B cat_C cat_D val_A val_B val_C val_D 
1 1  1  0  1  100  97  NULL NULL 
2 1  0  1  1  86  NULL 83  81 

我一直在使用CASE语句来检查IS NOT NULL在这里看到的例子在计算器,但是,这并不为我工作,我不认为,因为我可以有一个真的既缺失值和现存值空值。我可以创建两个CTE,一个与每个PIVOT,然后加入它们。这给了我想要的表格,但是它强制对表格进行聚集索引扫描两次,然后再加上连接运算符。这个表格非常大,而且性能很重要,所以我想尝试找到一种方法来在同一个聚集索引扫描中执行两个枢轴。

这可能吗?

回答

1

也许是交叉应用来解除您的数据。我应该补充一点,动态变化是一件小事。

Select * 
From (
      Select ID 
        ,B.* 
      From two_aggregate_pivot A 
      Cross Apply (values ('cat_'+category ,1) 
           ,('val_'+category ,value) 
         ) B (Item,Value) 
     ) src 
    Pivot (sum(value) for item in ([cat_A],[cat_B],[cat_C],[cat_D],[val_A],[val_B],[val_C],[val_D])) pvt 

返回

ID cat_A cat_B cat_C cat_D val_A val_B val_C val_D 
1 1  1  NULL 1  100  97  NULL NULL 
2 1  NULL 1  1  86  NULL 83  81 
+0

对不起,长延迟响应于此。我一直在试图弄清楚这个魔法是如何工作的。查看内部查询有帮助。我想我可以修改这个以适应我的情况,并且我将编辑这个评论以表明它如何执行相对于加入这两个枢纽。 –

+0

@RobertSievers对迟到的反应抱歉。我被拉走了。让我知道如果我可以帮助 –

+0

那么,这里是结果。这两种PIVIOT JOIN方法的效率比按照执行子树成本衡量的CROSS APPLY低30%。果然,CROSS APPLY只有一半的逻辑读取次数,但它需要两倍的CPU时间。实际持续时间几乎完全相同。所以,如果你有一个快速的磁盘,使用两个枢轴联接方法。如果您的磁盘速度较慢且CPU速度较快,请使用CROSS APPLY。 –