2016-03-13 3 views
-1

У меня есть запрос SQL Server, который должен выбрать тот, который был на первой и третьей неделе, на нашем портале, но не заходил на вторую неделю. Моя проблема в том, что запрос ниже занимает около 15 секунд для загрузки. Есть ли более быстрый способ или любая проблема по моему запросу?Запрос SQL Server В разделе

select 
    count(distinct id) 
from 
    table_x 
where 
    g in (319, 329) 
    and enable = 1 
    and Date between '2016-01-18' and '2016-01-24' --Third Week 
    and id in (select distinct id 
       from table_x 
       where g in (319, 329) 
       and enable = 1 
       and Date between '2016-01-05' and '2016-01-11' --First Week 
       and id not in (select distinct id 
           from table_x 
           where g in (319, 329) 
            and enable = 1 
            and Date between '2016-01-11' and '2016-01-17' --Second Week 
           ) 
      ) 
+2

Каков план выполнения вашего запроса? Насколько велики таблицы? Какой у вас индекс? – Dai

+0

«выбрать отдельный» - это дорогостоящая операция. Узнайте, когда следует использовать «select different» и когда не использовать его. Это делает ** НЕ помогать производительности ** в этом запросе. Идентификатор подсказки обычно уникален в таблице, поэтому «select different [id]» - это трата усилий. –

+0

- В таблице больше, чем в миллиметрах. - На самом деле идентификатор не является уникальным идентификатором, а ID пользователя. извините за пропущенное руководство ... – user4277756

ответ

2

Попробуйте использовать условные агрегаты (предложение с одним предложением и суммировать 3 случая) вместо нескольких проходов по таблице.

SELECT 
     COUNT(*) 
FROM (
     SELECT 
      user_id 
      , SUM(CASE WHEN [Date] BETWEEN '2016-01-18' AND '2016-01-24' THEN 1 ELSE 0 END) [ThirdWeek] 
      , SUM(CASE WHEN [Date] BETWEEN '2016-01-11' AND '2016-01-17' THEN 1 ELSE 0 END) [SecondWeek] 
      , SUM(CASE WHEN [Date] BETWEEN '2016-01-05' AND '2016-01-11' THEN 1 ELSE 0 END) [FirstWeek] 
     FROM table_x 
     WHERE x1.g IN (319, 329) 
      AND x1.enable = 1 
      AND x1.[Date] BETWEEN '2016-01-05' AND '2016-01-24' 
     GROUP BY 
      user_id 
) d 
WHERE [FirstWeek] > 0 
     AND [ThirdWeek] > 0 
     AND [SecondWeek] = 0 

В то время как я ожидал бы выше, чтобы быть хорошим вариантом, возможно использование EXISTS/NOT EXISTS может помочь, обратите внимание, вам не нужен отличие в следующем примере.

SELECT 
     COUNT(DISTINCT user_id) 
FROM table_x x1 
WHERE x1.g IN (319, 329) 
     AND x1.enable = 1 
     AND x1.[Date] BETWEEN '2016-01-18' AND '2016-01-24' --Third Week 
     AND EXISTS (
      SELECT 
        NULL 
      FROM table_x 
      WHERE g IN (319, 329) 
        AND enable = 1 
        AND Date BETWEEN '2016-01-05' AND '2016-01-11' --First Week 
        AND x1.user_id = table_x.user_id 
    ) 
     AND NOT EXISTS (
      SELECT 
        NULL 
      FROM table_x 
      WHERE g IN (319, 329) 
        AND enable = 1 
        AND Date BETWEEN '2016-01-11' AND '2016-01-17' --Second Week 
        AND x1.user_id = table_x.user_id 
    ) 
;