2016-06-14 3 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

@ Исправлены поля индекса 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 –

Смежные вопросы