2013-02-15 3 views
3

У меня есть запрос, который я пытаюсь оптимизировать, но не имел большого успеха. Существуют две таблицы: одна с основными данными и одна с отметками времени, когда произошли определенные события. Таблицы являются реляционными, используя общий ключ adID. Я пытаюсь выполнить запрос, который извлекает все временные метки и другие данные из основной таблицы. У меня это работает, но я пытаюсь оптимизировать, чтобы он работал быстрее.Как оптимизировать инструкцию SELECT с несколькими подзапросами

SELECT a.ID,a.repID,a.artistID, 
(
    SELECT TOP 1 c.timestamp 
    FROM Tracking AS c 
    WHERE statusID = 4 
    AND c.ID = a.ID 
    ORDER BY c.timestamp ASC 

) 
AS created, 
(
    SELECT TOP 1 d.timestamp 
    FROM Tracking AS d 
    WHERE statusID = 5 
    AND d.ID = a.ID 
    ORDER BY d.timestamp ASC 
) 
AS claimed, 
(
    SELECT TOP 1 p.timestamp 
    FROM Tracking AS p 
    WHERE statusID = 6 
    AND p.ID = a.ID 
    ORDER BY p.timestamp ASC 
) 
AS proof, 
(
    SELECT TOP 1 v.timestamp 
    FROM Tracking AS v 
    WHERE statusID = 8 
    AND v.ID = a.ID 
    ORDER BY v.timestamp ASC 
) 
AS approved, 
(
    SELECT count(ID) 
    FROM Tracking AS t 
    WHERE statusID = 6 
    AND t.ID = a.ID 
) 
AS proofcount 
FROM Advertising AS a 
WHERE a.statusID = 8 

Любая помощь по этому поводу оценивается. Я не слишком хорошо знаком с SQL Server, поэтому я не слишком разбираюсь в оптимизации таких запросов.

+0

Сколько строк делает возвращение запроса? Какие индексы у вас есть на 'Tracking'? –

ответ

2

Вы должны быть в состоянии использовать следующее:

SELECT a.ID, 
    a.repID, 
    a.artistID, 
    min(case when t.statusID = 4 then t.timestamp end) created, 
    min(case when t.statusID = 5 then t.timestamp end) claimed, 
    min(case when t.statusID = 6 then t.timestamp end) proof, 
    min(case when t.statusID = 8 then t.timestamp end) approved, 
    count(case when t.statusID = 6 then id end) proofcount 
FROM Advertising AS a 
LEFT JOIN Tracking t 
    on a.id = t.id 
WHERE a.statusID = 8 
GROUP BY a.ID, a.repID, a.artistID; 
+0

Спасибо, голубой. Это работало как шарм. – jgraening

+0

@jgraening Добро пожаловать, я рад помочь. Это в основном «PIVOT», вы также можете реализовать эту функцию для выполнения этой задачи. – Taryn

1

Я думаю, что следующий запрос получает то, что вы хотите:

select id, repid, artistid, 
     max(case when statusId = 4 and seqnum = 1 then timestamp end), 
     max(case when statusId = 5 and seqnum = 1 then timestamp end), 
     max(case when statusId = 6 and seqnum = 1 then timestamp end), 
     max(case when statusId = 8 and seqnum = 1 then timestamp end), 
     sum(case when statusId = 6 then 1 else 0 end) 
from (select a.ID, a.repID, a.artistID, t.statusId, t.timestamp 
      row_number() over (partition by a.id, t.statusId order by timestamp) as seqnum 
     from advertising a left outer join 
      tracking t 
      on a.id = t.id 
    ) t 
where seqnum = 1 
group by id, repid, artistid 

Он соединяет таблицу вместе и определяет самые ранние записи с помощью row_number(). Затем он выбирает только эти записи и группы другими полями.

Ваш запрос также фильтрует только те записи, которые имеют statusid = 8. Я не уверен, что это намеренно. Если да, то вы хотите, чтобы это having положения в конце запроса:

having sum(case when statusId = 8 then 1 else 0 end) > 0 
Смежные вопросы