簡體   English   中英

SQL Server查詢日期范圍之間一個月的總天數

[英]SQL Server query for total number of days for a month between date ranges

我有特定的日期范圍,例如

From Date        To Date
---------------------------    
2012-11-10       2012-11-15
2012-11-21       2012-11-22
2012-11-30       2012-12-01

我想編寫一個SQL查詢,該查詢計算兩個日期之間的天數總數和特定月份的天數總數

我想要的輸出是

No of days     month
--------------------
   9            11
   1            12

誰能幫我寫這個SQL查詢嗎?

理想情況下,您有一個名為“日期”的表,其中包含您將要使用的所有日期,例如1950年至2100年。此查詢將為您提供所需的結果:

  select dateadd(m,datediff(m, 0, d.thedate),0) themonth, count(1)
    from dates d
    join ranges r on d.thedate between r.[from date] and r.[to date]
group by datediff(m, 0, d.thedate)
order by themonth;

結果:

|   themonth | COLUMN_1 |
-------------------------
| 2012-11-01 |        9 |
| 2012-12-01 |        1 |

請注意,此查詢顯示的是第一天,而不是僅將“ 11”或“ 12”顯示為月份,如果您的范圍超過12個月或者在新的一年中無濟於事時,則不能很好地工作代替一個月。

如果沒有,您可以按照下面的擴展查詢在運行中虛擬地創建一個dates表:

;with dates(thedate) as (
  select dateadd(yy,years.number,0)+days.number
    from master..spt_values years
    join master..spt_values days
      on days.type='p' and days.number < datepart(dy,dateadd(yy,years.number+1,0)-1)
   where years.type='p' and years.number between 100 and 150
      -- note: 100-150 creates dates in the year range 2000-2050
      --       adjust as required
)
  select dateadd(m,datediff(m, 0, d.thedate),0) themonth, count(1)
    from dates d
    join ranges r on d.thedate between r.[from date] and r.[to date]
group by datediff(m, 0, d.thedate)
order by themonth;

此處提供了完整的工作示例: SQL Fiddle

嘗試這個

select ((day(date_to)) - (day(date_from))) as no_of_days,month(date_from)as month from tablename 

請原諒我編寫的SQL不好。
假設是月份差異。 在fromdate和todate之間是1。

架構

CREATE TABLE dateData
    (fromdate datetime, todate datetime)
;

INSERT INTO dateData
    (fromdate, todate)
VALUES
    ('2012-11-10', '2012-11-15'),
    ('2012-11-21', '2012-11-22'),
    ('2012-11-30', '2012-12-01')
;

SQL

select mth, sum(days) as daysInMth
from
(
select month(fromdate) as mth,
sum(case 
when month(fromdate) = month(todate) then datediff(dd, fromdate, todate)+1
else datediff(dd, fromdate, dateadd(mm, 1, fromdate) - day(fromdate)) + 1 end)
as days 
from dateData
group by month(fromdate)
union
select month(todate) as mth,
sum(case when month(todate) <> month(fromdate) then
datediff(dd, fromdate, dateadd(mm, 1, fromdate) - day(fromdate)) + 1
else 
case when month(todate) = month(fromdate) then 0 else
datediff(dd, convert(datetime, year(todate) + '-' + month(todate) + '-1'), todate) 
end
end) as days
from dateData
group by month(todate)
) aggregated
group by mth

在SQLFiddle上查看: http ://www.sqlfiddle.com/#!3 / 9f7da/56

我將其分為幾個步驟(每個步驟都有一個單獨的CTE):

declare @Ranges table (FromDate date not null,ToDate date not null)
insert into @Ranges (FromDate,ToDate) values
('20121110','20121115'),
('20121121','20121122'),
('20121130','20121201')

;with Months as (
    select
        DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010101') as MonthStart,
        DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010131') as MonthEnd
    from @Ranges
    union /* not all */
    select
        DATEADD(month,DATEDIFF(month,'20010101',ToDate),'20010101') as MonthStart,
        DATEADD(month,DATEDIFF(month,'20010101',ToDate),'20010131') as MonthEnd
    from @Ranges
), MonthRanges as (
    select
        CASE WHEN r.FromDate > m.MonthStart then r.FromDate ELSE m.MonthStart END as StartRange,
        CASE WHEN r.ToDate < m.MonthEnd then r.ToDate ELSE m.MonthEnd END as EndRange
    from
        @Ranges r
            inner join
        Months m
            on
                r.ToDate >= m.MonthStart and
                r.FromDate <= m.MonthEnd
)
select
    DATEPART(month,StartRange),
    SUM(DATEDIFF(day,StartRange,EndRange)+1) /* Inclusive */
from
    MonthRanges
group by
    DATEPART(month,StartRange)

首先, Months CTE查找我們可能感興趣的每個月的第一天和最后一天(*)。 然后, MonthRanges將此數據與原始范圍重新組合,並根據需要對其進行拆分,以便我們處理的每個期間僅代表一個月中的幾天。 然后,我們可以使用DATEDIFF來計算每個范圍的天數(並添加1,因為我們正在處理日期並且需要包含值)

(*)如果我們不處理跨多個月的任何范圍,並且在隨后的幾個月中沒有其他范圍開始或結束,則CTE Months將起作用。 如果您需要應對這種情況,我需要修改Months CTE。 例如,如果將('20120115','20120315') (而不添加其他范圍)添加到上述示例中,則使用上述示例將不會獲得2月份的結果。 我們需要應付這種情況嗎?


為了解決(*)中提到的情況,我們可以將上述查詢中的Months CTE替換為:

;With LastMonth as (
    select MAX(ToDate) as Mx from @Ranges
), MultiMonths as (
    select
        DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010101') as MonthStart,
        DATEADD(month,DATEDIFF(month,'20010101',FromDate),'20010131') as MonthEnd
    from @Ranges
    union all
    select
        DATEADD(month,1,MonthStart),
        DATEADD(month,1,MonthEnd)
    from MultiMonths
    where MonthStart <= (select Mx from LastMonth)
), Months as (
    select distinct MonthStart,MonthEnd from MultiMonths 
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM