2013-02-15 128 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”有哪些索引? – 2013-02-15 20:09:36

回答

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

谢谢bluefeet。这就像一个魅力。 – jgraening 2013-02-15 20:30:51

+0

@jgraening不客气,我很乐意提供帮助。这基本上是一个'PIVOT',你也可以实现这个功能来执行这个任务。 – Taryn 2013-02-15 20:31:41

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