每年总计数日(SQL)

每年总计数日(SQL),sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我的例子是: Code FromDate ToDate -- -------- ------- 101 15/12/2012 15/01/2013 101 30/11/2013 20/01/2014 我想计算两个日期之间的差异,一年中有多少天 ,如何使用SQ

我的例子是:

 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
使用以下命令:

   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
根据您当前编辑的问题,您应该使用

从TABLENAME中选择DATEDIFFday、“2012-06-05”和“2012-08-05”作为Year2012

例如:

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
您可以根据自己的需求对其进行操作

试试以下方法:

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

如果你需要更多的年份,你需要在子查询中添加更多的字段。

你需要结合一些不同的技术,才能得到你想要的结果

如果你有一个朋友,这会很有帮助。这些都是非常有用的东西,如果你不熟悉的话,很值得研究。我的问题是假设你没有。在这里,我使用了一个快速创建一个

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

-- 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')
;
询问 此查询将源数据连接到日历表。从开始日期到结束日期之间每天返回一条记录。我们使用日历表中的年份列对结果进行分组。计算记录会返回经过的总天数。为了计算年度小计,我们使用。此技术使用创建新列,这些列根据年份有条件地填充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) 
;
如果您已经有一个日历表,则可以通过删除CTE并更新联接来简化此查询

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

希望这有帮助

查看SUM。可能与GROUP BY组合。我没有第20122013列和第2014列计数日期,2012。关于计数,你是什么意思。根据您迄今为止的数据,给出2012年有17个等的逻辑?是的,从日期到年底。。。从明年开始到2013年1月15日小心:你可能需要避开2012,这样RDBMS就不会把它当成数字。小心:你可能需要避开2012,这样RDBMS就不会把它当成数字。
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