使用嵌套查询与CTE和性能影响

时间:2014-05-20 15:54:52

标签: sql sql-server sql-server-2008 tsql

我一直在使用sql,并且想知道将包含大量CTE的脚本转换为常规嵌套脚本是否以及如何有意义。我正在使用:

WITH cte_account_pricelevelid 
     AS (SELECT a.accountid, 
                a.pricelevelid 
         FROM   companypricelist a 
                JOIN(SELECT accountid 
                     FROM   crm_accountbase 
                     WHERE  defaultpricelevelid IS NULL) b 
                  ON a.accountid = b.accountid), 
     totals 
     AS (SELECT a.accountid, 
                a.pricelevelid 
         FROM   companypricelist a 
                JOIN(SELECT accountid 
                     FROM   crm_accountbase 
                     WHERE  defaultpricelevelid IS NULL) b 
                  ON a.accountid = b.accountid), 
     totalsgrouped 
     AS (SELECT pricelevelid, 
                Count(*) counts 
         FROM   totals 
         GROUP  BY pricelevelid), 
     final 
     AS (SELECT cte.accountid, 
                cte.pricelevelid, 
                frequency.counts 
         FROM   cte_account_pricelevelid cte 
                CROSS JOIN totalsgrouped frequency 
         WHERE  cte.pricelevelid = frequency.pricelevelid), 
     mycolumns 
     AS (SELECT b.accountid, 
                b.pricelevelid, 
                b.counts 
         FROM   (SELECT accountid 
                 FROM   crm_accountbase 
                 WHERE  defaultpricelevelid IS NULL) a 
                JOIN final b 
                  ON a.accountid = b.accountid), 
     e 
     AS (SELECT *, 
                Row_number() 
                  OVER ( 
                    partition BY accountid 
                    ORDER BY counts, pricelevelid ) AS Recency 
         FROM   mycolumns), 
     cte_result 
     AS (SELECT accountid, 
                pricelevelid 
         FROM   e 
         WHERE  recency = 1) 

SELECT a.accountid, 
       a.defaultpricelevelid, 
       b.pricelevelid 
FROM   crm_accountbase a 
       JOIN cte_result b 
         ON a.accountid = b.accountid 

我觉得在我的CTE中继续运行相同的查询是愚蠢的:

SELECT accountid 
                     FROM   crm_accountbase 
                     WHERE  defaultpricelevelid IS NULL

但我不知道如何绕过它。我想我可以把它转换成,但不知道是否会有任何性能提升。

select * from (select * from(select * from(...

是否有机会通过将其转换为嵌套SQL或仅简化CTE来极大地提高性能?如果是的话,你能帮我开始吗?

2 个答案:

答案 0 :(得分:2)

如果accountid被编入索引,则此联接将不会使用该索引 派生表没有索引

SELECT a.accountid, a.pricelevelid 
  FROM companypricelist a 
  JOIN (SELECT accountid 
          FROM crm_accountbase 
                     WHERE  defaultpricelevelid IS NULL) b 
    ON a.accountid = b.accountid

这将使用accountid的索引 即使没有关于accountid的索引,它也会更快

SELECT a.accountid, a.pricelevelid 
  FROM companypricelist a 
  JOIN crm_accountbase  b 
    ON a.accountid = b.accountid 
   AND b.defaultpricelevelid IS NULL

答案 1 :(得分:1)

我试着简化一下。介意运行它并让我知道结果?

WITH 
 totals 
 AS (SELECT a.accountid, 
            a.pricelevelid 
     FROM   companypricelist a 
            JOIN(SELECT accountid 
                 FROM   crm_accountbase 
                 WHERE  defaultpricelevelid IS NULL) b 
              ON a.accountid = b.accountid), 
 totalsgrouped 
 AS (SELECT pricelevelid, 
            Count(*) counts 
     FROM   totals 
     GROUP  BY pricelevelid), 
 final 
 AS (SELECT cte.accountid, 
            cte.pricelevelid, 
            frequency.counts 
     FROM   totals cte 
            CROSS JOIN totalsgrouped frequency 
     WHERE  cte.pricelevelid = frequency.pricelevelid), 
 mycolumns 
 AS (SELECT b.accountid, 
            b.pricelevelid, 
            b.counts 
     FROM   final b 
          JOIN totals a
              ON a.accountid = b.accountid), 
 e 
 AS (SELECT *, 
            Row_number() 
              OVER ( 
                partition BY accountid 
                ORDER BY counts, pricelevelid ) AS Recency 
     FROM   mycolumns) 

SELECT a.accountid, 
       a.defaultpricelevelid, 
       b.pricelevelid 
FROM   crm_accountbase a 
       JOIN e b 
         ON a.accountid = b.accountid 
WHERE b.recency = 1