2011-01-21 4 views
5

SQL Serverでは、求人情報の開始日と終了日を持つテーブルがあります。ユーザーが1ヶ月と1年を与えられたとき、私は、その投稿のために与えられた年/月に該当する開始日と終了日の間の日数を見つける必要があります。掲載開始日が2010年11月15日であり、終了日は2010年12月5日 ある場合レコードが特定の年/月内に存在する日数を選択します。

ので、出力は次のようになります。私はこれで壁に頭を叩いてきた

November 16 days 
December 5 days 
Total  21 days 

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部分の唯一の理由は、12月より前に、そして翌年の1月前に11月になることです。

+0

うわー、いくつかの啓示!もちろん、システムテーブルを使用することで、独自のものを作成して設定する必要がなくなります。しかし、ここで私の主なものは、あなたが日数を数えるために選んだ方法です。驚くばかり!私は他の人が投稿したものに似たバージョンを思いついたが、今私はそれを示すのは恥ずかしい。 –

+0

@Andriy - 答えをアップアップした方がいいと思うよ。 – RichardTheKiwi

+0

@cyberwiki:本当に、申し訳ありません。私はそれをupvotedと思った。自分の意図について私に思い出させるのはとても素敵です。 :) –

2

あなたは日がカウントされます上記DateDiff

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

dを使用します。

+0

私はdatediffの使い方を知っています。もし私が比較する2つの日付を持っていたら、私はそれを使用します。問題はより複雑で、2つの重複する日付間隔が関係します。 – ChrisOPeterson

+0

@ChirsOPeterson:あなたの質問を読み返しただけですが、重複していることは分かりませんでした。ああ待って、あなたが持っている出力は、あなたがそれをどのようにしたいのですか?そうであれば、OMG Poniesや他のサイトの看護師は、私がこの時点で不明であるため、これに答える必要があります。 – VoodooChild

+0

私が書き留めた特定の出力はあまり重要ではありません。私は値を取得する必要があります。オーバーラップは、ジョブの開始日と終了日の間の間隔から来て、開始日と終了日が完全にまたは部分的に一部である可能性がある各月です。 – ChrisOPeterson

1

EDIT:もう一つのマイナーな修正や2 ...

編集完全な答えを与えるために...

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) 
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 
+0

うわー、これは本当に興味深いね。ありがとう! – ChrisOPeterson

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; 

私は元のクエリから少し単純化しました。

+0

これは本当にクールな答えです。送信していただきありがとうございます。 – ChrisOPeterson

+0

お願いしてください:私はポイントを気にしませんが、ダウンボートした場合、私の答えについて不満足なことを私に知らせるためにわずか10秒かかりますか?私はいつも賢明に与えられたときに、訂正、さらには大幅な修正を改善し、愛するよう努力しています。 – ErikE

関連する問題