2016-06-14 67 views
1

我知道有一個更好的方法來完成我要在這裏完成的任務。雖然查詢起作用,但我擔心它會隨着數據集應用於增長而受到影響。性能調整tSQL查詢計數(*)和子查詢

我甚至不需要有人重寫我所擁有的東西,如果他們只是願意指出我應該研究的主題的方向,我將不勝感激。

我試圖返回與此查詢是一個或以上的某些狀態的記錄數的計數。

在此先感謝您的幫助!

SELECT (SELECT count(*) FROM TABLE1 c1 WHERE ( c1.U_KEY3 NOT LIKE 'z%' AND (c1.U_KEY1 = '' or c1.U_KEY1 IS NULL) ) ) AS 'STATUS is EMPTY' , (SELECT count(*) FROM TABLE1 c1 WHERE (c1.U_KEY3 NOT LIKE 'z%' AND LEFT(c1.U_KEY1,2) >= '70') ) AS 'STATUS > 70' , (SELECT count(*) FROM TABLE1 c1 WHERE (c1.U_KEY3 NOT LIKE 'z%' AND LEFT(c1.U_KEY1,2) >= '50') ) AS 'STATUS > 50' , (SELECT count(*) FROM TABLE1 c1 WHERE (c1.U_KEY3 NOT LIKE 'z%' AND LEFT(c1.U_KEY1,2) >= '30') ) AS 'STATUS > 30' , (SELECT count(*) FROM TABLE1 c1 WHERE (c1.U_KEY3 NOT LIKE 'z%' AND LEFT(c1.U_KEY1,2) >= '10') ) AS 'STATUS > 10'

+0

你對'TABLE1'任何指標?查詢的運行速度可能比您想象的要快。 –

+0

表中有多少行?你有嘗試過使用JOIN而不是子查詢嗎? – FLICKER

+0

@Tim U_KEY字段被索引。目前表中只有1200行,運行良好,但有可能增長到100,000。 –

回答

2

你可以使用CASE聲明滾動所有的子查詢到一個查詢:

SELECT 
    SUM(CASE WHEN c1.U_KEY1 = '' OR c1.U_KEY1 IS NULL THEN 1 ELSE 0 END) AS 'STATUS IS EMPTY', 
    SUM(CASE WHEN LEFT(c1.U_KEY1,2) >= '70'   THEN 1 ELSE 0 END) AS 'STATUS > 70', 
    SUM(CASE WHEN LEFT(c1.U_KEY1,2) >= '50'   THEN 1 ELSE 0 END) AS 'STATUS > 50', 
    SUM(CASE WHEN LEFT(c1.U_KEY1,2) >= '30'   THEN 1 ELSE 0 END) AS 'STATUS > 30', 
    SUM(CASE WHEN LEFT(c1.U_KEY1,2) >= '10'   THEN 1 ELSE 0 END) AS 'STATUS > 10' 
FROM TABLE1 c1 
WHERE c1.U_KEY3 NOT LIKE 'z%' 

但是這可能不是個人的子查詢跑得一樣快。

+0

這應該會更快,因爲只有一個表/索引掃描。如果有U_KEY1和U_KEY3的索引,它將是一個索引掃描和一些流聚合。這並不可怕,這取決於這兩列的大小。 – siride

+0

@siride我知道這將是一個單一的表掃描,但'CASE'的陳述看起來對我來說非常令人討厭。感謝您的評論。 –

+0

他們是,但他們只是表達式,可以很快計算出來。查詢也可能是可並行化的。 – siride

1

我會扭轉這個問題是這樣的:

DECLARE @t TABLE (Id INT, U_Key1 VARCHAR(4) null); 

INSERT INTO @t (id,U_Key1) 
VALUES 
(1,null), 
(2,'902'), 
(3,'452'), 
(4,'401'), 
(5,'103'), 
(6,'359'), 
(7,'335'), 
(8,'772'), 
(9,'143'), 
(10,'222'), 
(11,'664'), 
(12,'992'), 
(13,'122'), 
(14,'332'), 
(15,'421'), 
(16,'622'), 
(17,'982'), 
(18,'1234'), 
(19,null), 
(20,'012'); 

WITH A AS (
    SELECT CAST(LEFT(U_Key1,2) AS INT) val FROM @t 
), limits AS (
    SELECT 10 limitval, 'Status >= 10' limittext 
    UNION ALL 
    SELECT 30 , 'Status >= 30' 
    UNION ALL 
    SELECT 50 , 'Status >= 50' 
    UNION ALL 
    SELECT 70 , 'Status >= 70' 

), Counts AS (
    SELECT 'Status is empty' Limittext, COUNT(id) Count FROM @t 
    WHERE U_Key1 IS null 
    UNION ALL 
    SELECT l.limittext, COUNT(A.val) Count FROM A 
    CROSS JOIN limits l 
    WHERE A.val >= l.limitval 
    GROUP BY l.limittext 
    ) 
    SELECT * FROM Counts 

產生的結果是:

Status is empty 2 
Status >= 10 17 
Status >= 30 12 
Status >= 50 6 
Status >= 70 4 
+0

不錯!謝謝@PeterO –