最近,我注意到我的一个存储过程花费了很长时间才能运行。
我认为我的问题有点过于具体而无法正确提出,所以我认为我要求解决我的问题以及如何简化复杂陈述的建议。
我有一个"结果"我的SSMS数据库中的表。我有的选择查询会根据结果生成排名。
排名是根据作为参数提供的日期生成的,并根据过去四年的结果计算。
去年的结果得到100%的积分,一年到两年前得到75%,2到3年前得到50%,3到4年前得到25%。< / p>
我还得到另一个名为&#34; Rank Change&#34;的计算列,这是自提供日期之前的最后一个结果以来的排名变化。
查询如下。
由于这是一个复杂的查询,可能很难简化,如果可能,您会如何简化此查询?
你使用什么技术来简化像这样的查询,如果有的话?
IF (@Date < '2000-01-01')
BEGIN
SET @Date = '2000-01-01'
END
DECLARE @LatestContestDate DATE
SET @LatestContestDate = ( SELECT TOP 1 Date
FROM Results
WHERE Date < @Date
ORDER BY Date DESC
)
SET @LatestContestDate = DATEADD(DD, -1, @LatestContestDate)
SELECT Band.Name ,
Area.Name ,
( ISNULL(( SELECT SUM(R2.Points) /*Calculates points*/
FROM Results R2
WHERE R2.Date > DATEADD(YY, -1, @Date)
AND R2.Date < DATEADD(DD, 1, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT ( SUM(R2.Points) * 0.75 )
FROM Results R2
WHERE R2.Date < DATEADD(YY, -1, @Date)
AND R2.Date > DATEADD(YY, -2, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT ( SUM(R2.Points) * 0.5 )
FROM Results R2
WHERE R2.Date < DATEADD(YY, -2, @Date)
AND R2.Date > DATEADD(YY, -3, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT ( SUM(R2.Points) * 0.25 )
FROM Results R2
WHERE R2.Date < DATEADD(YY, -3, @Date)
AND R2.Date > DATEADD(YY, -4, @Date)
AND R2.BandID = R1.BandID
), 0) ) AS PointsTotal , /*Below Calculates rank change*/
( ( ROW_NUMBER() OVER ( ORDER BY ( ISNULL(( SELECT
SUM(R2.Points)
FROM Results R2
WHERE R2.Date > DATEADD(YY,
-1,
@LatestContestDate)
AND R2.Date < DATEADD(DD,
1,
@LatestContestDate)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT
( SUM(R2.Points)
* 0.75 )
FROM
Results R2
WHERE
R2.Date < DATEADD(YY,
-1,
@LatestContestDate)
AND R2.Date > DATEADD(YY,
-2,
@LatestContestDate)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT
( SUM(R2.Points)
* 0.5 )
FROM
Results R2
WHERE
R2.Date < DATEADD(YY,
-2,
@LatestContestDate)
AND R2.Date > DATEADD(YY,
-3,
@LatestContestDate)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT
( SUM(R2.Points)
* 0.25 )
FROM
Results R2
WHERE
R2.Date < DATEADD(YY,
-3,
@LatestContestDate)
AND R2.Date > DATEADD(YY,
-4,
@LatestContestDate)
AND R2.BandID = R1.BandID
), 0) ) DESC ) )
- ( ROW_NUMBER() OVER ( ORDER BY ( ISNULL(( SELECT
SUM(R2.Points)
FROM
Results R2
WHERE
R2.Date > DATEADD(YY,
-1, @Date)
AND R2.Date < DATEADD(DD,
1, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT
( SUM(R2.Points)
* 0.75 )
FROM
Results R2
WHERE
R2.Date < DATEADD(YY,
-1, @Date)
AND R2.Date > DATEADD(YY,
-2, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT
( SUM(R2.Points)
* 0.5 )
FROM
Results R2
WHERE
R2.Date < DATEADD(YY,
-2, @Date)
AND R2.Date > DATEADD(YY,
-3, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT
( SUM(R2.Points)
* 0.25 )
FROM
Results R2
WHERE
R2.Date < DATEADD(YY,
-3, @Date)
AND R2.Date > DATEADD(YY,
-4, @Date)
AND R2.BandID = R1.BandID
), 0) ) DESC ) ) ) AS RankChange
FROM Results R1
INNER JOIN Band ON R1.BandID = Band.ID
INNER JOIN Area ON Band.AreaID = Area.ID
WHERE ( ISNULL(( SELECT SUM(R2.Points)
FROM Results R2
WHERE R2.Date > DATEADD(YY, -1, @Date)
AND R2.Date < DATEADD(DD, 1, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT ( SUM(R2.Points) * 0.75 )
FROM Results R2
WHERE R2.Date < DATEADD(YY, -1, @Date)
AND R2.Date > DATEADD(YY, -2, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT ( SUM(R2.Points) * 0.5 )
FROM Results R2
WHERE R2.Date < DATEADD(YY, -2, @Date)
AND R2.Date > DATEADD(YY, -3, @Date)
AND R2.BandID = R1.BandID
), 0)
+ ISNULL(( SELECT ( SUM(R2.Points) * 0.25 )
FROM Results R2
WHERE R2.Date < DATEADD(YY, -3, @Date)
AND R2.Date > DATEADD(YY, -4, @Date)
AND R2.BandID = R1.BandID
), 0) ) > 0
GROUP BY Band.Name ,
Area.Name,
BandID
ORDER BY PointsTotal DESC
答案 0 :(得分:3)
使用条件聚合进行点计算。类似的东西:
select (sum(case when r2.Date > DATEADD(year, -1, @Date) and r2.Date < DATEADD(day, 1, @Date)
then r2.points else 0
end) +
sum(case when r2.Date < DATEADD(year, -1, @Date) and r2.Date > DATEADD(year, -2, @Date)
then r2.points else 0
end) * 0.75 +
. . .
)
from results r2
where r2.BandID = r1.BandID and
r2.Date >= dateadd(year, -4, @Date)
然后将其放入子查询中,以及用于row_number的类似查询的类似表达式。然后引用SELECT
,ROW_NUMBER()
和WHERE
中子查询的表达式。这样可以将子查询的数量从16减少到1或2。
您可以使用results(BandId, Date)
上的索引对此进行优化。
在SQL Server 2012+中,您可以使用累积总和来执行所需的操作。
答案 1 :(得分:0)
很难确切地说明如何在不知道底层架构和表格如何的情况下修改select语句。那就是说我会先看看sql server management studio中的execution plan,然后看看查询瓶颈是什么:缺少索引,缺点,IO,缺少统计信息等。
这是一个非常好的link,可以让您开始快速调整查询的性能: