每年的总计数日(SQL)

时间:2017-02-07 09:42:27

标签: sql sql-server sql-server-2008

我的例子:

 Code            FromDate          ToDate                 
 --              --------           -------        
 101               15/12/2012         15/01/2013   
 101               30/11/2013         20/01/2014 

我想计算两个日期之间的差异,今年多少天 ,我怎么能用SQL做到这一点? 结果如下:

 Code    No.day     2012   2013  2014
 --      ------     ----   ----  ----
 101       82        17     46    19

4 个答案:

答案 0 :(得分:0)

使用此:

   SELECT Code,SUM(No.day) AS No.day, SUM(2012) AS 2012, SUM(2013) AS 2013, SUM(2014) AS 2014
    FROM TABLENAME GROUP BY Code

根据您当前(编辑)的问题,您应该使用

SELECT DATEDIFF(day,'2012-06-05','2012-08-05') AS Year2012 From TABLENAME

例如:

SELECT DATEDIFF(day, '2014/01/01', '2014/04/28');
Result: 117

SELECT DATEDIFF(hour, '2014/04/28 08:00', '2014/04/28 10:45');
Result: 2

SELECT DATEDIFF(minute, '2014/04/28 08:00', '2014/04/28 10:45');
Result: 165

您可以根据自己的要求进行操作。

答案 1 :(得分:0)

尝试类似:

select Code,sum([2012])+sum([2013])+sum([2014]) as 'No.days',sum([2012]),sum([2013]),sum([2014]) from(
select Code,
    case when datepart(yy,fromdate)=datepart(yy,todate) and datepart(yy,fromdate)=2012 then  datediff(dd,fromdate, todate)
    when datepart(yy,fromdate)=2012 and  datepart(yy,todate)>2012 then datediff(dd,fromdate,dateadd(yy,1,dateadd(dd,-datepart(dy,DATEADD(yy,1, fromdate)),fromdate)))
    when datepart(yy,fromdate)<2012 and  datepart(yy,todate)=2012 then  DATEPART(dy,todate)
    end as '2012',
    case when datepart(yy,fromdate)=datepart(yy,todate) and datepart(yy,fromdate)=2013 then  datediff(dd,fromdate, todate)
    when datepart(yy,fromdate)=2013 and  datepart(yy,todate)>2013 then  datediff(dd,fromdate,dateadd(yy,1,dateadd(dd,-datepart(dy,DATEADD(yy,1, fromdate)),fromdate)))
    when datepart(yy,fromdate)<2013 and  datepart(yy,todate)=2013 then  DATEPART(dy,todate)
    end as '2013',
    case when datepart(yy,fromdate)=datepart(yy,todate) and datepart(yy,fromdate)=2014 then  datediff(dd,fromdate, todate)
    when datepart(yy,fromdate)=2014 and  datepart(yy,todate)>2014  then  datediff(dd,fromdate,dateadd(yy,1,dateadd(dd,-datepart(dy,DATEADD(yy,1, fromdate)),fromdate)))
    when datepart(yy,fromdate)<2014 and  datepart(yy,todate)=2014 then  DATEPART(dy,todate)
    end as '2014'
    from myTable
    ) as daystable
group by Code

如果您需要更多年,则需要在子查询中添加更多字段。

答案 2 :(得分:0)

您需要结合几种不同的技巧,以获得您所追求的结果。

如果您有calendar table,这会有所帮助。这些是非常有用的东西,如果你不熟悉那么值得研究。我的查询假设您没有。在这里,我使用了recursive CTE来动态创建一个。

样本数据

提示:以我们可以分享的格式提供样本数据,提高您的问题获得答案的几率。

-- Table variables are a good way to share sample data.
DECLARE @Sample TABLE
    (
        Code        INT,
        FromDate    DATE,
        ToDate      DATE
    )
;

INSERT INTO @Sample
    (
        Code,
        FromDate,
        ToDate
    )
VALUES
    (101, '2012-12-15', '2013-01-15'),
    (101, '2013-11-30', '2014-01-20')
;

查询

此查询将源数据连接到日历表。在from和to日期之间每天返回一条记录。使用日历表中的年份列,我们将结果分组。计算记录将返回通过的总天数。要计算年份小计,我们使用conditional aggregation。此技术使用case expression创建新列,这些列根据年份有条件地填充1或0。

/* Returns date counts, split by
 * year.
 */
WITH CalendarTable AS
    (
        /* This CTE returns 1 record for each day 
         * between Jan 1st 2012 and Dec 31st 2014.
         */
            SELECT
                CAST('2012-01-01' AS DATE)  AS [Date],
                2012                        AS [Year]

        UNION ALL

            SELECT
                DATEADD(DAY, 1, [Date])         AS [Date],
                YEAR(DATEADD(DAY, 1, [Date]))   AS [Year]
            FROM
                CalendarTable 
            WHERE
                [Date] < '2014-12-31'
    ) 
SELECT
    s.Code,
    COUNT(*)                                            AS [No.Day],
    SUM(CASE WHEN ct.[Year] = 2012 THEN 1 ELSE 0 END)   AS [2012],
    SUM(CASE WHEN ct.[Year] = 2013 THEN 1 ELSE 0 END)   AS [2013],
    SUM(CASE WHEN ct.[Year] = 2014 THEN 1 ELSE 0 END)   AS [2014]
FROM
    @Sample AS s
        INNER JOIN CalendarTable AS ct      ON  ct.[Date] >= s.FromDate 
                                            AND ct.[Date] < s.ToDate    
GROUP BY
    s.Code
OPTION 
    (MAXRECURSION 1096) 
;

返回

Code    No.day     2012   2013  2014
--      ------     ----   ----  ----
101       82        17     46    19

如果您已有日历表,则可以通过删除CTE并更新连接来简化此查询。

答案 3 :(得分:0)

SELECT     code,fromdate,todate,datediff(dd,fromdate,todate),
                datediff(dd,case when year(fromdate) < 2012 then '1/1/2012' when year(fromdate) = 2012 then fromdate else '12/31/2012' end,case when year(todate) = 2012 then todate else '12/31/2012'end)'2012',
                datediff(dd,case when year(fromdate) < 2013 then '1/1/2013' when year(fromdate) = 2013 then fromdate else '12/31/2013' end,case when year(todate) = 2013 then todate else '12/31/2013'end)  '2013',
                datediff(dd,case when year(fromdate) < 2014 then '1/1/2014' when year(fromdate) = 2014 then fromdate else '12/31/2014' end,case when year(todate) < 2014 then '1/1/2014' when year(todate) = 2014 then todate else '12/31/2014'end)  '2014' FROM (SELECT     '101' AS code, datefromparts(2012,12,15) AS fromdate, datefromparts(2013,1,15) AS todate
          UNION
          SELECT     '101' AS code, datefromparts(2013,11,30) AS fromdate, datefromparts(2014,1,20) AS todate
          Union 
          SELECT     '101' AS code, datefromparts(2014,11,30) AS fromdate, datefromparts(2016,1,20) AS todate) AS s

希望这会有所帮助