这个聚合查询如何找到正确的值

时间:2015-01-27 17:22:40

标签: sql sql-server

我无法理解这段代码。它实际上似乎工作,但我不明白活动年和月的正确值如何“找到”得到适当的最小和最大?或者它是否运行所有排列最高?这对我来说很奇怪。

我确实理解dateadd是如何工作的,而不是查询实际上是如何工作的。这可能是一个糟糕的问题,因为我实际上并不需要帮助解决问题,只是深入了解其工作原理。

select 
    EmployeeNumber,
    sum(BaseCalculation) as BaseCalculation,
    min(dateadd(mm, (ActivityYear - 1900) * 12 + ActivityMonth - 1 , 0)) as StartDate,
    max(dateadd(mm, (ActivityYear - 1900) * 12 + ActivityMonth - 1 , 0)) as EndDate
from 
    Compensation 
where 
    1=1
    -- and
group by 
    EmployeeNumber

3 个答案:

答案 0 :(得分:0)

它将列ActivityYearActivityMmonth转换为日期。它是通过计算自1900年以来的月数并将它们添加到零时间来实现的。因此,2000年1月将变成像Jan,100这样的事情。这看起来像是一个非常神秘的计算,因为大约2000年的日期并不是真的有用。

当然,这假设ActivityYear是近年来可识别的。

我会将年份和月份转换为月初的第一天,如下所示:

min(cast(cast(ActivityYear * 10000 + ActivityMonth + 1 as varchar(255)) as date)

答案 1 :(得分:0)

Sql Server将计算该语句的每个值,然后仅返回最小值和最大值

虽然我不能肯定地说sql server在内部以这种方式执行,但我想到它的方式我想象引擎剥离组和所有聚合函数,运行该查询。然后只需总结/找到最小值等。

答案 2 :(得分:0)

对于minmax函数调用,算法

dateadd(mm, (ActivityYear - 1900) * 12 + ActivityMonth - 1 , 0)

您的查询使用此算法从Compensation表计算所有可能的日期。然后,您选择最短日期为StartDate,最大日期为EndDate

这是返回正确的最大值和最小值的方式。

请注意,dateadd签名为DATEADD (datepart , number , date )

由于最后一个参数为0,因此您可以将月份(mm)添加到算法中计算的数字中,并返回从0开始的相应日期。

查看此信息以获取更多信息:https://msdn.microsoft.com/en-us/library/ms186819.aspx

相关问题