选择某个年/月内记录的天数

时间:2011-01-21 22:20:14

标签: sql sql-server sql-server-2005 tsql

在sql server中,我有一个表,其中包含作业发布的开始和结束日期。在给定用户一个月和一年的情况下,我需要找到该发布的给定年/月的开始日期和结束日期之间的天数。

因此,如果发布开始日期是2010/11/15,结束日期是2010/12/05 然后输出应该是:

November  16 days
December  5 days
Total     21 days

我一直用这个打我的头靠在墙上,而且我的想法很新鲜。

6 个答案:

答案 0 :(得分:2)

您想使用DateDiff

DateDiff("d",[StartDate],[EndDate])

上面的d将计算天数。

答案 1 :(得分:2)

这可能是最简洁的答案。

declare @start datetime, @end datetime
select @start = '20101115', @end = '20101205'

select datename(month,@start+number), count(*)
from master..spt_values
where type='P'
  and number between 0 and datediff(d,@start,@end)
group by datename(month,@start+number), convert(char(6),@start+number,112)
order by convert(char(6),@start+number,112)

它适用于最长2048天(7 - 8年)的范围,但如果您需要,可以延长更长时间(仅根据要求 - 看起来会更复杂)。

convert(char部分的唯一原因是让11月在12月之前以及明年1月之前出现。

答案 2 :(得分:1)

编辑:另一个小修正或两个...

编辑给出完整答案......

declare @user_start_date datetime
set @user_start_date = '1/1/2011'
declare @user_end_date datetime
set @user_end_date = '1/10/2011'
declare @job_start_date datetime
set @job_start_date = '1/2/2011'
declare @job_end_date datetime
set @job_end_date = '1/11/2011'

declare @nextStartDate datetime;
set @nextStartDate = str(datepart(mm, @user_start_date)) + '/1/' + str(datepart(yyyy, @user_start_date))
declare @nextEndDate datetime;
set @nextEndDate = dateadd(dd,-1,dateadd(mm,1,@nextStartDate))

create table #monthYears(startDate datetime, endDate datetime)
while (@nextStartDate < @user_end_date) begin
    insert into #monthYears values(@nextStartDate, @nextEndDate)
    set @nextStartDate = dateadd(mm,1,@nextStartDate)
    set @nextEndDate = dateadd(dd,-1,dateadd(mm,1,@nextStartDate))
end

-- Print Months
select [month], [year], case when dayCount < 0 then 0 else dayCount end from (
select month(startDate) month, year(startDate) year , datediff(dd, 
    case when startDate > @job_start_date then startDate else @job_start_date end, 
    case when endDate < @job_end_date then endDate else @job_end_date end) dayCount
from #monthYears) temp

select datediff(dd, 
    case when @user_start_date > @job_start_date then @user_start_date else @job_start_date end, 
    case when @user_end_date < @job_end_date then @user_end_date else @job_end_date end)

答案 3 :(得分:1)

这在SQL中有点难,但这会创建一个包含月份(整数)和天数的表格。

我会留给你将整数转换为月份并添加总数

SET NOCOUNT on

Declare @StartDate datetime
Declare @EndDate datetime
Declare @StartDateNormalized datetime
Declare @EndDateNormalized datetime


SET @StartDate = '2010/11/15' 
SET @EndDate = '2011/2/05'

declare @result table ( month int, days int)


--Normalize the Inputs

SET @StartDateNormalized = cast(Month(@startDate) as varchar) + '/1/' + cast(year(@startDate) as varchar)
SET @EndDateNormalized = cast(Month(@EndDate) as varchar) + '/1/' + cast(year(@EndDate) as varchar)

insert into @result 
values 
(   MONTH(@StartDateNormalized),
    DateDiff(Day, @StartDate, DateAdd(month, 1, @StartDateNormalized ) )
)

SET @StartDateNormalized = DateAdd(month, 1, @StartDateNormalized ) 

WHILE (@StartDateNormalized < @EndDateNormalized)
BEGIN

insert into @result 
values 
(   MONTH(@StartDateNormalized),
   DateDiff(Day, @StartDateNormalized, DateAdd(month, 1, @StartDateNormalized ) )  
)

   SET @StartDateNormalized = DateAdd(month, 1, @StartDateNormalized ) 
END

insert into @result 
values 
(   MONTH(@EndDateNormalized),
   DateDiff(Day, @EndDateNormalized, @EndDate    ) + 1 
)


select * from @result

答案 4 :(得分:1)

DECLARE
   @StartDate datetime,
   @EndDate datetime;
SET @StartDate = '20101115';
SET @EndDate = '20101205';

WITH Mos AS (
   SELECT
      Number,
      DateAdd(Month, Number, @StartDate - Day(@StartDate) + 1) MoDate
   FROM master.dbo.spt_values
   WHERE
      Type = 'P'
      AND Number <= DateDiff(Month, @StartDate, @EndDate)
), Dys AS (
   SELECT
      MoDate,
      DateDiff(
         Day,
         CASE WHEN Number = 0 THEN @StartDate ELSE MoDate END,
         CASE WHEN Number = DateDiff(Month, @StartDate, @EndDate) THEN @EndDate ELSE DateAdd(Month, 1, MoDate) - 1 END
      ) + 1 Cnt
   FROM Mos
)
SELECT
   Year(MoDate) Yr,
   Coalesce(DateName(Month, MoDate), 'Total') Mo,
   Convert(varchar(11), Sum(Cnt)) + ' day' + CASE WHEN Sum(Cnt) = 1 THEN '' ELSE 's' END Descr
FROM Dys
GROUP BY MoDate
WITH ROLLUP
ORDER BY Grouping(MoDate), MoDate;

这是一个表版本,以防你想同时使用多个版本:

CREATE TABLE AccountDates (
   AccountCode varchar(10) NOT NULL CONSTRAINT PK_AccountDates PRIMARY KEY CLUSTERED,
   StartDate datetime,
   EndDate datetime
);

INSERT AccountDates VALUES ('BLINKEN', '20101115', '20101205');
INSERT AccountDates VALUES ('KRAM', '20101027', '20110118');
INSERT AccountDates VALUES ('NUVU', '20101207', '20101207');

WITH Mos AS (
   SELECT
      AccountCode,
      D.StartDate,
      D.EndDate,
      Number,
      DateAdd(Month, Number, D.StartDate - Day(D.StartDate) + 1) MoDate
   FROM
      AccountDates D
      INNER JOIN master.dbo.spt_values V ON V.Number <= DateDiff(Month, D.StartDate, D.EndDate)
   WHERE
      V.Type = 'P'
), Dys AS (
   SELECT
      AccountCode,
      MoDate,
      DateDiff(
         Day,
         CASE WHEN Number = 0 THEN StartDate ELSE MoDate END,
         CASE WHEN Number = DateDiff(Month, StartDate, EndDate) THEN EndDate ELSE DateAdd(Month, 1, MoDate) - 1 END
      ) + 1 Cnt
   FROM Mos
)
SELECT
   AccountCode,
   Year(MoDate) Yr,
   Coalesce(DateName(Month, MoDate), 'Total') Mo,
   Convert(varchar(11), Sum(Cnt)) + ' day' + CASE WHEN Sum(Cnt) = 1 THEN '' ELSE 's' END Descr
FROM Dys
GROUP BY AccountCode, MoDate
WITH ROLLUP
HAVING Grouping(AccountCode) = 0
ORDER BY
   AccountCode,
   Grouping(MoDate),
   MoDate;

我从原始查询中略微简化了一些事情。

答案 5 :(得分:0)

  

以下示例确定   当前之间的天数差异   日期和产品的订单日期   在AdventureWorks数据库中。

USE AdventureWorks;
GO
SELECT DATEDIFF(day, OrderDate, GETDATE()) AS NumberOfDays
FROM Sales.SalesOrderHeader;
GO

http://msdn.microsoft.com/en-us/library/ms189794%28v=sql.90%29.aspx