如何根据飞行员的生日和当前日期计算SQL日期

时间:2012-07-22 18:14:49

标签: sql database date sql-server-2008-express

因此,飞行员必须每6个月(半年)以及每年(每年)进行如此多的飞行时间和飞行飞行。最大的痛苦是这些时期的开始和结束日期都是基于他们的出生月份。

您可以在此处找到有关我的架构的更多信息:Design decision: Table schema for partial dates in order to calculate time spans (SQL Server)

DECLARE @date Date
SET @date = '1985-04-12'

DECLARE @diffInYears INT
SET @diffInYears = DATEDIFF(yy, @date, GETDATE())

DECLARE @currentBirthDate Date
SET @currentBirthDate = (SELECT dateadd(yyyy, @diffInYears, @date))

SELECT DATEADD(dd, -DAY(DATEADD(m,1,@currentBirthDate)), DATEADD(m,7,@currentBirthDate)) semiAnnualDateEnd, 
        DATEADD(dd, -DAY(DATEADD(m,1,@currentBirthDate)), DATEADD(m,13,@currentBirthDate)) annualDateEnd

RESULTS:

semiAnnualDateEnd - annualDateEnd
   2012-10-31     -  2013-04-30

现在,这很好,这些是我想要这个特定例子的日期。

然而,当我们来到2012年11月1日时,我希望halfAnnualDateEnd成为2013-04-30。

此外,当2013年到来时(2013年1月1日),年度日期结束将成为2014-04-30,当我希望它保持2013-04-30直到2013-05-01到来,然后因为它成为2014-04-30(半年的类似情况)。

我不想让这些日期与特定飞行员保持静态关联。也就是说,我不想在Pilot表中保留一些具有这些字段的字段。但是,我想将它们用于显示和计算。例如,需要显示每个飞行员当前的半年和年度飞行时间,以及在任何特定时间点显示他们的“当前”统计数据的快照。

编辑:我正在使用SQL Server 2008 Express RC

编辑2:我想我应该将@currentBirthDate更改为(SELECT DATEADD(yyyy,@ diffInYears - 1,@ date)。然后,我需要在下面做一个案例陈述(继续实验)

2 个答案:

答案 0 :(得分:1)

半年度日期的规则似乎是:在该月增加五个月并且到月底。月底可能是个问题。所以,让我们把它改为“增加六个月,到月底减去一天”。 (我将这个逻辑基于你的例子。)

以下表达式执行此操作:

select dateadd(d, -1,
               cast(cast(year(bd)+(case when month(bd)+6 > 12 then 1 else 0 end) as varchar(255))+'-'+
                    cast(case when month(bd)+7> 12 then month(bd)+6-12 else month(bd) end as varchar(255))+'-'+
                    '1' as date))
from (select cast('2011-11-01' as date) bd) t

它对日期的year()和month()值进行日期算术运算。然后它将它们作为一个字符串重新组合在一起,转换为日期,并减去1天。

我认为类似的东西也适用于你的年份日期。

答案 1 :(得分:0)

DECLARE @pilotID INT
SET @pilotID = 1

DECLARE @birthDate DATE  
SET @birthDate = (SELECT birthDate FROM Pilot WHERE pilotID = @pilotID)

DECLARE @diffInYears INT  
SET @diffInYears = DATEDIFF(yy, @birthDate, GETDATE())  

DECLARE @currentBirthDate DATE  
SET @currentBirthDate = (DATEADD(yyyy, @diffInYears - 1, @birthDate))  

DECLARE @firstSixMonthStart DATE
DECLARE @firstSixMonthEnd DATE  
DECLARE @secondSixMonthStart DATE
DECLARE @secondSixMonthEnd DATE  

SET @firstSixMonthStart = (DATEADD(dd,-(DAY(DATEADD(m,1,@currentBirthDate))-1),DATEADD(m,1,@currentBirthDate)))
SET @firstSixMonthEnd = (DATEADD(dd, -DAY(DATEADD(m,1,@currentBirthDate)), DATEADD(m,7,@currentBirthDate))) 
SET @secondSixMonthStart = (DATEADD(dd,-(DAY(DATEADD(m,1,@currentBirthDate))-1),DATEADD(m,7,@currentBirthDate)))
SET @secondSixMonthEnd = (DATEADD(dd, -DAY(DATEADD(m,1,@currentBirthDate)), DATEADD(m,13,@currentBirthDate)))  


DECLARE @semiAnnualStart AS DATE
DECLARE @semiAnnualEnd AS DATE 
DECLARE @annualStart AS DATE
DECLARE @annualEnd AS DATE 

SET @semiAnnualStart =  CASE   
                            WHEN GETDATE() > (DATEADD(dd, -DAY(DATEADD(m,1,@firstSixMonthEnd)), DATEADD(m,7,@firstSixMonthEnd)))  
                                THEN (DATEADD(yyyy, 1, @firstSixMonthStart))  
                            WHEN GETDATE() > @firstSixMonthEnd  
                                THEN @secondSixMonthStart      
                            ELSE @firstSixMonthStart 
                        END     

SET @semiAnnualEnd =    CASE   
                            WHEN GETDATE() > (DATEADD(dd, -DAY(DATEADD(m,1,@firstSixMonthEnd)), DATEADD(m,7,@firstSixMonthEnd)))  
                                THEN (DATEADD(yyyy, 1, @firstSixMonthEnd))  
                            WHEN GETDATE() > @firstSixMonthEnd   
                                THEN @secondSixMonthEnd    
                            ELSE @firstSixMonthEnd 
                        END     

SET @annualStart =      CASE   
                            WHEN GETDATE() > @secondSixMonthEnd THEN (DATEADD(yyyy, 1, @firstSixMonthStart))  
                            ELSE @firstSixMonthStart
                        END         

SET @annualEnd =        CASE   
                            WHEN GETDATE() > @secondSixMonthEnd THEN (DATEADD(yyyy, 1, @secondSixMonthEnd))  
                            ELSE @secondSixMonthEnd  
                        END

SELECT @semiAnnualStart semiStart, @semiAnnualEnd semiEnd, 
        @annualStart annualStart, @annualEnd annualEnd,
        @firstSixMonthStart firstStart, @firstSixMonthEnd firstEnd,
        @secondSixMonthStart secondStart, @secondSixMonthEnd secondEnd,
        COUNT(*) semiSorties, ISNULL(SUM(hours), 0) semiSortieHours
FROM PilotLog
WHERE pilotID = @pilotID
    AND topLevelPosition = 'AVO'
    AND flightDate BETWEEN @semiAnnualStart AND @semiAnnualEnd

结果:

semiStart   semiEnd     annualStart annualEnd   firstStart  firstEnd    secondStart secondEnd   semiSorties semiSortieHours
2012-05-01  2012-10-31  2011-11-01  2012-10-31  2011-11-01  2012-04-30  2012-05-01  2012-10-31  1           1.7

这最终起作用了...问题是,我将需要为整个摘要页面上的每个飞行员执行此操作。另外,我将需要为她想要的快照计算这种出击信息。她希望回到任何特定的月份,看到快照,列出每个航班以及他们完成该航班时的出击统计数据。这个SQL应该适用于这些情况,我只需要在这里和那里稍微改变它。

(编辑:为什么我的代码不能横向滚动..?我不希望它包装。没关系,这只是Internet Explorer看起来像)