2016-11-09 9 views
0

私は、SQL Server 2014を使用していますが、私が抜粋を以下に示しているの私のSQLデータベース内(NonRoomBundleと呼ばれる)次の表は、持っている:SQL ServerでこのロジックのCASE文構文を記述する方法は?

ResaID  StayDate     BundleDate     BundleID 
    50   NULL      2016-03-03 00:00:00.000   123 
    50   2016-02-28 00:00:00.000 NULL        3 
    50   2016-02-29 00:00:00.000 NULL        3 
    50   2016-03-01 00:00:00.000 NULL        3 
    50   2016-03-02 00:00:00.000 NULL        3 
    50   2016-03-03 00:00:00.000 NULL        3 
    50   2016-03-04 00:00:00.000 NULL        3 
    50   2016-03-05 00:00:00.000 NULL        3 
    50   2016-03-02 00:00:00.000 NULL        3 
    56   NULL      2016-04-02 00:00:00.000   120 
    56   2016-04-01 00:00:00.000 NULL        25 
    56   2016-04-02 00:00:00.000 NULL        25 
    56   2016-04-03 00:00:00.000 NULL        25 

BundleDate列がBundleIdがすべきで有効StayDateを示し私は私に次のような出力を提供しますクエリを記述する必要がある123

こと:BundleId上記のよう

ResaID  StayDate     BundleDate     BundleID 
    50   NULL      2016-03-03 00:00:00.000   123 
    50   2016-02-28 00:00:00.000 NULL        3 
    50   2016-02-29 00:00:00.000 NULL        3 
    50   2016-03-01 00:00:00.000 NULL        3 
    50   2016-03-02 00:00:00.000 NULL        3 
    50   2016-03-03 00:00:00.000 NULL       123 
    50   2016-03-04 00:00:00.000 NULL       123 
    50   2016-03-05 00:00:00.000 NULL       123 
    50   2016-03-02 00:00:00.000 NULL       123 
    56   NULL      2016-04-02 00:00:00.000   120 
    56   2016-04-01 00:00:00.000 NULL        25 
    56   2016-04-02 00:00:00.000 NULL       120 
    56   2016-04-03 00:00:00.000 NULL       120 

はBundleDateである「2016年3月2日」からのように123になります。 SQLについての私の知識は私にCASEステートメントがトリックをするべきだと私に伝えますが、私はそれを書くのが苦労しています。私はこれまでにこれに達しました:

SELECT StayDate 
     ,BundleDate 
     ,(CASE WHEN BundleDate >= StayDate THEN .... 
    FROM NonRoomBundle 

答えて

0

これはあなたの後のことですか?

with NonRoomBundle (StayDate, BundleDate , BundleID) 
as 
(
select NULL as StayDate, '2016-03-02 00:00:00.000' as BundleDate , 123 as BundleID 
union 
select '2016-02-28 00:00:00.000' as StayDate, NULL as BundleDate , 3 as BundleID 
union 
select '2016-02-29 00:00:00.000' as StayDate, NULL as BundleDate , 3 as BundleID 
union 
select '2016-03-01 00:00:00.000' as StayDate, NULL as BundleDate , 3 as BundleID 
union 
select '2016-03-02 00:00:00.000' as StayDate, NULL as BundleDate , 3 as BundleID 
union 
select '2016-03-03 00:00:00.000' as StayDate, NULL as BundleDate , 3 as BundleID 
union 
select '2016-03-04 00:00:00.000' as StayDate, NULL as BundleDate , 3 as BundleID 
union 
select '2016-03-05 00:00:00.000' as StayDate, NULL as BundleDate , 3 as BundleID 
) 

SELECT StayDate 
,BundleDate 
,(
CASE 
WHEN StayDate < (select max(BundleDate) from NonRoomBundle) THEN 3 
else 123 
END 
) 
FROM NonRoomBundle 
+0

それは動作しません。 – user3115933

+0

また、BundleIDに明示的な値を設定したくないので、テーブル全体を実行する必要があります。私は私の質問にテーブルの抽出物のみを示しました。 – user3115933

+0

もっと多くのデータ例を提供できますか? –

0

あなたがこの試すことができます:私がやっていること

declare @tblInput table (ResaID int, StayDate datetime, BundleDate datetime, BundleID int) 

insert into @tblInput(ResaID, StayDate, BundleDate, BundleID) 
values (50, NULL, '2016-03-07', 123), 
     (50,'2016-02-28', NULL, 3), 
     (50,'2016-02-29', NULL, 3), 
     (50,'2016-03-01', NULL, 3), 
     (50,'2016-03-02', NULL, 3), 
     (50,'2016-03-03', NULL, 3), 
     (50,'2016-03-04', NULL, 3), 
     (50,'2016-03-05', NULL, 3), 
     (50,'2016-03-02', NULL, 3), 
     (56,NULL, '2016-04-02', 120), 
     (56,'2016-04-01', NULL, 25), 
     (56,'2016-04-02', NULL, 25), 
     (56,'2016-04-03', NULL, 25) 

;WITH cte (ResaID, StayDate, BundleDate, BundleID) 
as 
(
    select ResaID, StayDate, BundleDate, BundleId 
     from @tblInput 
    where BundleDate is not null 
) 
SELECT t1.ResaID 
     ,t1.StayDate 
     ,t1.BundleDate 
     ,ISNULL(t2.BundleID, t1.BundleID) as BundleID 
    FROM @tblInput t1 
    left join cte t2 on t2.BundleDate <= ISNULL(t1.StayDate, GETDATE()) 
         and t1.ResaID = t2.ResaID; 

は次のとおりです。最初の束の日付(アンカー行)で値を分離し、その後、私はon句を使用して、最初のテーブルと結合しましたcase句に記載されています。あなたの要求に基づいてより有効な日付にISNULL関数のGETDATE()を置き換えることができます。

EDIT:コードを更新しました。 EDIT2:必要な情報を反映するようにコードを更新しました。

+0

ありがとうございます。私は追加情報で私の質問を更新しました。 BundleDateでエラーが発生しましたが、今修正しました。どうぞご覧ください。 – user3115933

+0

あなたの努力に感謝します。あなたのソリューションは、私が探しているものの逆をしています。これは、BundleDateがStayDateよりもGREATERではなくStayDateよりも小さいすべてのレコードのBundleIDの値を置き換えています。あなたが提案したものが正しい解決策に非常に近いので、何かを微調整する必要があると思います。 – user3115933

+0

私はそれを得ました。 > = <=で置換するだけでした。私が投票できるようにあなたのソリューションを編集できますか?再度、感謝します。 – user3115933

0

これは複雑に見えるかもしれません、と私は提案してるものよりも、別の方法があるかもしれないが、ここではこの猫を肌する一つの方法です:

declare @bundleDates table (
    BundleDate date, 
    BundleID int, 
    RunningNo int 
) 

insert into @bundleDates 
select 
    BundleDate, 
    BundleID, 
    row_number() over (order by (select null)) 
from NonRoomBundle 
where BundleDate is not null order by BundleDate asc 

declare @NonRoomBundle table (
    StayDate date, 
    BundleDate date, 
    BundleID int 
) 

declare 
    @tmpBundleDate date, 
    @tmpBundleID int, 
    @tmpRunningNo int 

declare cur cursor local for select BundleDate, BundleID, RunningNo from @bundleDates 
open cur 
fetch next from cur into @tmpBundleDate, @tmpBundleID, @tmpRunningNo 
while @@fetch_status = 0 
    begin 
     if exists (select RunningNo from @bundleDates where RunningNo = @tmpRunningNo + 1) 
      begin 
       declare @currBundleDate date, @nextBundleDate date 
       set @currBundleDate = @tmpBundleDate 
       set @nextBundleDate = (select BundleDate from @bundleDates where RunningNo = @tmpRunningNo + 1) 

       insert into @NonRoomBundle 
       select 
        StayDate, 
        BundleDate, 
        BundleID 
       from NonRoomBundle 
       where 
        StayDate is null 
        and BundleID = @tmpBundleID 

       union 

       select 
        StayDate, 
        BundleDate, 
        case 
         when StayDate < @currBundleDate then BundleID 
         when StayDate >= @currBundleDate then @tmpBundleID 
        end as BundleID 
       from NonRoomBundle 
       where 
        StayDate is not null 
        and year(StayDate) <= year(@currBundleDate) 
        and month(StayDate) <= month(@currBundleDate) 
        and StayDate < @nextBundleDate 
      end 
     else 
      begin 
       insert into @NonRoomBundle 
       select 
        StayDate, 
        BundleDate, 
        BundleID 
       from NonRoomBundle 
       where 
        StayDate is null 
        and BundleID = @tmpBundleID 

       union 

       select 
        StayDate, 
        BundleDate, 
        case 
         when StayDate < @tmpBundleDate then BundleID 
         when StayDate >= @tmpBundleDate then @tmpBundleID 
        end as BundleID 
       from NonRoomBundle 
       where 
        StayDate is not null 
        and year(StayDate) >= year(@tmpBundleDate) 
        and month(StayDate) >= month(@tmpBundleDate) 
      end 

     fetch next from cur into @tmpBundleDate, @tmpBundleID, @tmpRunningNo 
    end 
close cur 
deallocate cur 


select * from @NonRoomBundle 
関連する問題