如何使用多个子查询优化SELECT语句

时间:2013-02-15 20:05:52

标签: sql sql-server

我有一个查询,我正在尝试优化,但没有取得多大成功。有两个表,一个包含主数据,另一个包含特定事件发生时的时间戳。这些表是使用adID的公共密钥进行关联的。我正在尝试执行一个查询,从主表中提取所有时间戳和其他数据。我有它的工作,但我正在尝试优化,所以它运行得更快。

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不太熟悉,所以我不太熟悉优化这些查询。

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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