我正在尝试加速查询,但我无法看到我需要做的查询如何,旧的查询使用的是慢速的函数,所以我已经替换它们,这会加快查询速度但是当完整的查询放在一起它没有更快。问题是我必须为每个子查询调用我的主表,其中有10个以下是查询的一部分,因为完整的东西有点长,应该让你知道问题是什么。
非常感谢!
托马斯
新守则 -
SELECT DISTINCT CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) AS MemMonth,
(SELECT COUNT(DISTINCT me_csID) AS Expr1
FROM dbo.tblMembershipStatus
WHERE (ms_memID IN (@memID))
AND (msDurationType IN (@memType))
AND (CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, MainMonth.msValidFrom) + 1, MainMonth.msValidFrom) AS FLOAT)) AS DATETIME))
BETWEEN CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME)
AND CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidUntil) + 1, msValidUntil) AS FLOAT)) AS DATETIME)) AS active
FROM tblMembershipStatus AS MainMonth
WHERE (CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) BETWEEN @StartDate AND @EndDate)
GROUP BY msValidFrom
ORDER BY MemMonth
相同的代码,但它看起来如何 -
SELECT Purple7Master.dbo.fnc_GetMonthStart(msValidFrom) AS [MemMonth],
(SELECT COUNT(DISTINCT me_csID) AS Expr1
FROM dbo.tblMembershipStatus
WHERE (ms_memID IN (@memID))
AND (msDurationType IN (@memType))
AND (Purple7Master.dbo.fnc_GetMonthStart(MainMonth.msValidFrom)
BETWEEN Purple7Master.dbo.fnc_GetMonthStart(msValidFrom)
AND Purple7Master.dbo.fnc_GetMonthStart(msValidUntil))) AS [active]
FROM tblMembershipStatus AS MainMonth
WHERE (Purple7Master.dbo.fnc_GetMonthStart(msValidFrom) BETWEEN @StartDate AND @EndDate)
GROUP BY Purple7Master.dbo.fnc_GetMonthStart(msValidFrom)
ORDER BY MemMonth
答案 0 :(得分:0)
这里有很多工作要做,这只是你开始的部分答案。
WHERE (CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) BETWEEN @StartDate AND @EndDate)
首先这是非常低效的。您正在处理表中的每一行并强制进行全表扫描。
您必须将其更改为
WHERE msValidFrom between @calculated_StartDate and @calculated_endDate
并在msValidFrom上创建一个索引,加速了事情。
你也可以在选择之前做一些计算:
declare @Calculated_date datetime
SET @calcualted_date = cast(floor( ......... @no_calculated_date.....))
答案 1 :(得分:0)
让我试着改写一下你所拥有的内容,以及那些完全浪费的转换会导致你的查询被删除。您希望在给定时间段@StartDate,@ EndDate之间为特定成员ID @memID和成员资格持续时间@memType
的每个月基数计数显示表格结构和示例数据会有所帮助,但让我们看一下您的转化正在做什么以及为什么它可能过度杀伤。
CAST( FLOOR( CAST( DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) AS MemMonth,
看着内心的......
DatePart(dd, msValidFrom) returns the DAY a member is valid from ex: 12th of the month
DateAdd( dd, -DatePart(dd, msValidFrom) +1, msValidFrom ) is basically saying
Take Dec 12, subtract 12 days to get to last day of November 30, then add 1 to bring it
back to the first day of December, so you have the month 12 (December)
为什么不使用
DatePart( mm, msValidFrom ) to give you 12 (December).
SQL处理任何日期/时间组件。
这本身就可以简化你的头痛。
为了帮助,我会在你的tblMembershipStatus ON上有一个索引
( ms_memID, msDurationType, msValidFrom )
现在,您的OUTER WHERE子句。你在那里做同样的事情,如果日期上有索引。我会以适当的月份开始/月末格式提供你的@StartDate和@EndDate
开始日期类似于
@StartDate = '2013-11-01' (which defaults to 12:00:00 AM)
@EndDate = '2013-12-01' (which also defaults to 12:00:00 AM)
然后,你的WHERE子句可能是
WHERE
ms_memID in @memID
AND msDurationType in @memType
AND msValidFrom >= @StartDate
AND msValidFrom < @EndDate (notice not <= end date which would include Dec 1)
最后你的小组。您可以通过msValidFrom获得它,但是没有聚合(sum,min,max,avg),因为您正在进行DISTINCT,如果在给定月份,您有人在一个月的所有不同日期注册成为会员,你将获得每一天的计数,但这是一个非常艰难的方式。我建议按照
的方式做点什么SELECT
datepart( yyyy, MS.msValidFrom ) memberYear,
datepart( mm, MS.msValidFrom ) memberMonth,
COUNT(*) as ActiveMembers
from
dbo.tblMembershipStatus MS
WHERE
MS.ms_memID = @memID
AND MS.msDurationType = @memType
AND MS.msValidFrom >= @StartDate
AND MS.msValidUntil < @EndDate
group by
datepart( yyyy, MS.msValidFrom ),
datepart( mm, MS.msValidFrom )
但同样,这是没有看到实际的表结构,示例数据,也没有预期的期望结果(建议您更新原始帖子。不要使用制表符对齐,但空格,然后按Ctrl + K来阻止格式化)