【问题标题】:How to calculate SQL dates based on pilot's birthday as well as current date如何根据飞行员的生日和当前日期计算 SQL 日期
【发布时间】:2012-07-22 18:14:48
【问题描述】:

因此,飞行员必须在每 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 日时,我希望 semiAnnualDateEnd 变为 2013-04-30。

另外,当 2013 年到来时(2013 年 1 月 1 日),yearDateEnd 将变为 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)。然后,我需要在下面做一个案例陈述(继续实验)

【问题讨论】:

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


    【解决方案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 天吗?也只是挑剔,但你真的需要转换为 varchar(255) 吗?你不能为年和月做 varchar(4) 吗?
    • 是的,我的意思是到月初减去一天。这是找到月底的最简单方法。 varchar 的大小,只要它足够大并且
    【解决方案2】:
    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 的样子)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      相关资源
      最近更新 更多