2016-11-16 11 views
0

の範囲で私の問題である:スプリット複数のデータは、ここでは複数行に

私はテーブルを持っている:

FIELD_1 FIELD_2 FIELD_N StartDate  EndDate  OTHER_FIELDS 
value1 value2 valuen 2016-01-12 2016-05-12 othervalues 
value3 value4 valuen 2015-01-12 2015-05-12 othervalues 

私は他の複数の行に複数の行のデータ範囲を分割する必要があります。以下のように

:ここ

StartDate     EndDate     other_columns 
2016-01-12    2016-05-12    myvalues 
2016-01-13    2016-05-12    myvalues 
2016-01-14    2016-05-12    myvalues 
..      ..      .. 
..      ..      .. 
2015-01-12    2015-05-12    myvalues 
2015-01-13    2015-05-12    myvalues 
..      ..      .. 

は私のコードです:

CREATE TABLE [dbo].[OUTPUT_TABLE](
    [STARTDATE] [datetime] NULL, 
    [ENDDATE] [datetime] NULL, 
    [OTHER_FIELDS] [nvarchar](30) NULL, 
) ON [PRIMARY] 

GO 

DECLARE @cnt INT 
DECLARE @startDate DATETIME 
DECLARE @endDate DATETIME 
DECLARE @incr INT 
DECLARE @tempDate DATETIME 

SET @startDate=(SELECT [StartDate] 
       FROM [dbo].[INPUT_TABLE]) 
SET @endDate=(SELECT [EndDate] 
       FROM [dbo].[INPUT_TABLE]) 
SET @cnt=Datediff(dd, @startDate, @endDate) 
SET @incr=0 
SET @tempDate=Dateadd(dd, @incr, Cast(@startDate AS DATETIME)) 

WHILE @cnt >= 0 
    BEGIN 
     IF @cnt = 0 
     BEGIN 
      INSERT INTO [dbo].[OUTPUT_TABLE] 
      VALUES  (@tempDate, 
         @endDate, 
         NULL 
         ); 
     END 
     ELSE 
     BEGIN 
      INSERT INTO [dbo].[OUTPUT_TABLE] 
      VALUES  (@tempDate, 
         Dateadd(dd, Datediff(dd, 0, @tempDate) + 1, -1), 
         NULL 
         ); 
     END 


     SET @tempDate=Dateadd(dd, @incr + 1, Dateadd(dd, Datediff(dd, 0, 
                 @startDate) 
              , 0)) 
     SET @[email protected] - 1 
     SET @[email protected] + 1 
    END 

現時点でコードが入力テーブルの上に単一の行を有する場合には作業が、私がする必要が検討しています私は現在解決策を見つけていない複数の行にそれを繰り返します。誰でも私が問題を解決するのを手伝ってくれる人がいますか?

は ルイージ

+0

これらの日付範囲の間に1日の行が必要ですか? – SQLChao

+0

はい、正確です。複数の行の場合.. – LuigiVe

+0

2つの日付の間の日付ごとに行を挿入しようとしていると思いますか?このためには、集計表が必要です。ここにループを張る必要は全くありません。ここでは、このトピックに関する素晴らしい記事です。 http://www.sqlservercentral.com/articles/T-SQL/62867/ –

答えて

0

はたぶん、日付を含むカレンダーのテーブルを作成し、それに参加し、事前にあなたに よろしく大変ありがとうございました。

SELECT * 
FROM input_table it 
JOIN calendar c on c.date >= it.startdate and c.date <= it.enddate 
1

ここでは、集計表を活用してこれを短時間で行う方法を示します。ループの必要は全くありません。あなたが望むなら、ctesを使ってその場で集計テーブルを作成することができます。私のシステムでは、私はこのように定義されたビューを持っています。

create View [dbo].[cteTally] as 

WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 
select N from cteTally 

本当に集計表に慣れているはずです。これは、 "t-sqlのスイスアーミーナイフ"と呼ばれています。

ここで、問題の設定を完了するためのテーブルとデータが必要です。

create table #InputTable 
(
    SomeID int identity primary key 
    , StartDate date 
    , EndDate date 
    , OTHER_FIELDS varchar(20) 
) 

insert #InputTable 
(
    StartDate 
    , EndDate 
    , OTHER_FIELDS 
) 
select '2016-01-12', '2016-05-12', 'othervalues' union all 
select '2015-01-12', '2015-05-12', 'othervalues' 

CREATE TABLE [dbo].[OUTPUT_TABLE](
    [STARTDATE] [datetime] NULL, 
    [ENDDATE] [datetime] NULL, 
    ThisDate date, 
    [OTHER_FIELDS] [nvarchar](30) NULL, 
) ON [PRIMARY] 

問題の設定がすべて完了したので、実際にはソリューションの作業を開始できます。集計表を利用することで、この超シンプルなものになります。単一の挿入ステートメント以上のものはありません。

insert OUTPUT_TABLE 
(
    STARTDATE 
    , ENDDATE 
    , ThisDate 
    , OTHER_FIELDS 
) 
select it.StartDate 
    , it.EndDate 
    , DATEADD(day, t.N - 1, it.StartDate) 
    , it.OTHER_FIELDS 
from #InputTable it 
join cteTally t on t.N <= DATEDIFF(day, it.StartDate, it.EndDate) + 1 

ここで、これが本当にうまくいくかどうかを確認できます。

select * 
from OUTPUT_TABLE 

これを見てください。 243行.1つはベース表の各開始日と終了日の値の間の日付です。ループもカーソルもありません。残されているのは、私たちの脚の仕事の証拠を取り除くための少しクリーンアップです。

drop table OUTPUT_TABLE 
drop table #InputTable 
関連する問題