Sql 选择某一年/月内记录存在的天数

Sql 选择某一年/月内记录存在的天数,sql,sql-server,sql-server-2005,tsql,Sql,Sql Server,Sql Server 2005,Tsql,在sql server中,我有一个表,其中包含职位发布的开始日期和结束日期。如果用户给出了一个月和一年,我需要找到该帖子的开始日期和结束日期之间的天数 因此,如果发布开始日期为2010/11/15,结束日期为2010/12/05 那么输出应该是: November 16 days December 5 days Total 21 days 我一直在用这本书把我的头撞在墙上,我的想法都没有了。你想用它吗 DateDiffd、[StartDate]、[EndDate] 上面的d将计天

在sql server中,我有一个表,其中包含职位发布的开始日期和结束日期。如果用户给出了一个月和一年,我需要找到该帖子的开始日期和结束日期之间的天数

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

November  16 days
December  5 days
Total     21 days
我一直在用这本书把我的头撞在墙上,我的想法都没有了。

你想用它吗

DateDiffd、[StartDate]、[EndDate]

上面的d将计天

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


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

编辑以给出完整答案

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)

这在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
这里有一个表格版本,以防您想同时使用多个:

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;

我从最初的查询中简化了一些内容。

这可能是最简洁的答案

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年,但如果您只需要根据要求延长,则可以延长更长的时间-这看起来更复杂


convertchar部分的唯一原因是让11月在12月之前,也在明年1月之前。

我知道如何使用datediff。如果我有两个日期可以比较,那么我会使用它。这个问题更复杂,涉及两个重叠的日期间隔。@ChirsOPeterson:我刚刚重读了你的问题,但我没有看到你提到的重叠是什么?哦,等等,你的输出,这就是你想要的吗?如果是这样的话,OMG Ponies或其他一些网站大师将不得不回答这个问题,因为我现在还不确定。我写下的具体输出并不那么重要。我只需要得到这些值。重叠来自于作业开始日期和结束日期之间的间隔,然后每个月的开始日期和结束日期可能全部或部分是其中的一部分。哇,这个看起来真的很有趣。谢谢哇,一些启示!当然,使用系统表不需要创建和填充我们自己的表。但对我来说最重要的是你选择的计算天数的方式。令人惊叹的我已经提出了一个类似于其他人发布的版本,但现在我羞于展示它:如此琐碎@cyberwiki:非常正确,对不起。我还以为我投了更高的票呢。非常感谢你提醒我自己的意图好主意。利用低容量做一些通常相当昂贵的事情是一个很好的技巧。当我有机会的时候,与其他方法相比,检查大型数据集的I/O会很有趣。这真的很酷。我仍在试图弄清楚它是如何运作的。拜托,拜托,拜托:我不在乎要点,但如果你投了反对票,你能用10秒钟的时间让我知道我的答案有什么不满意的地方吗?我总是努力提高,喜欢纠正,即使是重大的纠正,当我委婉地给予的时候。
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;
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)