避免重复与慢速子查询

时间:2016-08-09 08:11:49

标签: sql-server join subquery views

我有一个MS SQL查询,使用TransactionID链接到下面的表(12m行)。我需要总结Cost,但仅当AnalysisGroupID在给定列表中时,例如。 (56,62)

+---------------+-----------------+-------+
| TransactionID | AnalysisGroupID | Cost  |
+---------------+-----------------+-------+
| 1118850       | 57              | 5.00  |
+---------------+-----------------+-------+
| 1118850       | 56              | 10.00 |
+---------------+-----------------+-------+
| 1118850       | 57              | 4.00  |
+---------------+-----------------+-------+
| 1118850       | 56              | 7.00  |
+---------------+-----------------+-------+
| 1132443       | 57              | 3.00  |
+---------------+-----------------+-------+
| 1132443       | 56              | 8.00  |
+---------------+-----------------+-------+
| 1132443       | 57              | 9.00  |
+---------------+-----------------+-------+
| 1145784       | 62              | 10.00 |
+---------------+-----------------+-------+
| 1145784       | 63              | 5.00  |
+---------------+-----------------+-------+
| 1145784       | 62              | 4.00  |
+---------------+-----------------+-------+
| 1145784       | 63              | 7.00  |
+---------------+-----------------+-------+
| 1145786       | 62              | 9.00  |
+---------------+-----------------+-------+
| 1145786       | 63              | 8.00  |
+---------------+-----------------+-------+
| 1145786       | 42              | 3.00  |
+---------------+-----------------+-------+

问题是如果我只是在TransactionID上直接加入我得到重复项,因为一个TransactionID可以对多个AnalysisGroupID有一个Cost。

但是,如果我尝试使用子查询或事先创建视图,那么:

create view SorDeliveryTransactionAnalysisCarriage

as

select
    sdta.transactionid,
    sum(sdta.Cost) as Cost
from
        SorDeliveryTransactionAnalysis sdta         
where
        sdta.AnalysisGroupID in (56, 62)
    and 
        sdta.Cost > 0
group by
    sdta.transactionid

...性能大幅降低,我猜是因为在这种情况下我可以加入TransactionID之前需要对表的所有12m行求和?

无论如何,我可以做我的连接以避免重复,但不必事先处理表格中的每一行?

修改
 我应该提到一些关于我的情况的具体问题,这有助于我找到解决方案:

我需要运行此查询数百次,将其他表中的不同ID插入到查询的其他部分,但重要的是我只需要定期执行整个过程,即每周或每两周一次。

2 个答案:

答案 0 :(得分:1)

尝试使用Filtered索引限制行

Select 
Transactionid,
sum(Case when analysisgroupid in (56,62) then cost else 0.00 end) as 'summ'
from
Yourtable
group by 
Transactionid

当你有一个分组时,SQL将尝试获取分组中的列的不同值并执行其余的操作

在您的情况下,由于transactionid上的重复,因此无法使用Unqiue idnex,因此在transactionid上创建一个过滤索引,限制分析组,如下所示。

create index nci_test
on dbo.yourtable(transactinid)
include(cost)
where analysusgroupid in(56,62)

答案 1 :(得分:0)

因为这只需要每周或每两周完成一次,并且不需要使用实时数据不断更新,所以最有效的方法是:

  1. 创建问题中指定的视图。
  2. 从视图中创建一个静态表,如下所示:
  3. 从MyView中选择* into MyTable

    1. 在主查询中引用表而不是视图。
    2. 这个解决方案意味着总计12m行的主要工作只进行一次。之后我们可以通过在TransactionID

      上链接来引用静态表