2014-05-20 31 views
4

我一直在使用sql一段時間,並想知道是否以及如何將包含大量CTE的腳本轉換爲常規嵌套腳本。我使用的是:使用嵌套查詢與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,以極大地提高性能的機會?如果是這樣,你願意讓我開始?

+0

零增益。 CTE只是語法。 CTE只是插入到最終查詢中。 – Paparazzi

+0

謝謝!那麼你會說,按照我的方式使用CTE通常是更清潔的嗎?而不是從一堆選擇(從(從...中選擇(從...選擇)? –

+0

從這篇文章:http://stackoverflow.com/questions/23751253/do-i-need-a-recursive-cte-要更新一個表,它依賴本身#comment36520286_23751253用戶861051069712110711711710997114說,有一個性能問題與CTE的http://screencast.com/t/S22Pqjqqfvl這是不正確的? –

回答

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 
+0

非常有趣!!使用「和」this方式總是比使用「where」更快 –

+0

並且永遠不會比哪裏慢,你讀過我的答案嗎?主要的因素是使用accountid的索引,爲什麼你有兩個相同的CTE? – Paparazzi

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