2

アイテムのリストからアイテム、日付範囲の要約、sql-2008 の日付を生成しようとしています。

DECLARE @RoomDays AS TABLE (
    [RoomID] [int] NOT NULL,
    [DateOf] [date] NOT NULL,
    [Segment] [char](1) NOT NULL
)

INSERT INTO @RoomDays
VALUES 
('1','2013-07-03','1'),
('1','2013-07-04','1'),
('1','2013-07-05','6'),
('1','2013-07-15','6'),
('1','2013-07-16','6'),
('2','2013-07-08','1'),
('2','2013-07-09','1'),
('2','2013-07-10','6'),
('2','2013-07-11','6'),
('2','2013-07-12','1'),
('2','2013-07-13','1'),
('3','2013-07-19','6')

私が取得しようとしている結果:

RoomID  DateFrom    DateThru    Segments     NumDays
1       2013-07-03  2013-07-05  1,1,6        3
1       2013-07-15  2013-07-16  6,6          2
2       2013-07-08  2013-07-13  1,1,6,6,1,1  6
3       2013-07-19  2013-07-19  6            1

これを行う方法について頭を悩ませることはできません...

..これはおそらくセグメント列の場合です:

( 
SELECT CAST( ltrim(rtrim(SegmentID)) + ', ' AS VARCHAR(MAX))
from @RoomDays where roomid = rd.roomid
FOR XML PATH ('')
)+' ' as Segments,
--

ヘルプやガイダンスをいただければ幸いです。

4

2 に答える 2

0

日付範囲を取得することは、古くからのギャップと島の問題です。セグメントの連結は、説明したような XML トリックで行われます。

SQLフィドルを使用した完全なソリューションは次のとおりです。http://sqlfiddle.com/#!3/d4a961/11

質問のコードとテーブル変数を使用すると、コードは次のようになります。

WITH groupedDays AS (
SELECT
RoomID
,DateOf
,Segment
,DATEADD(day,-row_number() OVER (partition by RoomID order by DateOf),DateOf) AS Island
FROM @RoomDays
)

SELECT
outerTable.RoomID
,MIN(outerTable.DateOf) AS DateFrom
,MAX(outerTable.DateOf) AS DateThru
,STUFF((
    SELECT ', ' + innerTable.Segment
    FROM groupedDays AS innerTable
    WHERE innerTable.RoomID = outerTable.RoomID
    AND innerTable.Island = outerTable.Island
    ORDER BY innerTable.DateOf
    FOR XML PATH('')
),1,1,'')
,COUNT(*) AS NumDays

FROM groupedDays AS outerTable

GROUP BY
outerTable.RoomID
,outerTable.Island

ORDER BY
outerTable.RoomID
,outerTable.Island
于 2013-07-10T09:36:04.423 に答える
0

以下のコードは、サンプル データを使用した完全な動作例です。ここにいくつかの役立つリンクがあります。

列値からの T-SQL CSV

再帰的 CTE

SET NOCOUNT ON
GO

    DECLARE @RoomDays TABLE 
    (
         [RoomID] INT NOT NULL
        ,[DateOf] DATE NOT NULL
        ,[Segment] CHAR(1) NOT NULL
    )

    INSERT INTO @RoomDays ([RoomID], [DateOf], [Segment] )
    VALUES   ('1','2013-07-03','1')
            ,('1','2013-07-04','1')
            ,('1','2013-07-05','6')
            ,('1','2013-07-15','6')
            ,('1','2013-07-16','6')
            ,('2','2013-07-08','1')
            ,('2','2013-07-09','1')
            ,('2','2013-07-10','6')
            ,('2','2013-07-11','6')
            ,('2','2013-07-12','1')
            ,('2','2013-07-13','1')
            ,('3','2013-07-19','6')

    ;WITH DataSource ([RoomID], [DateOf], [Segment], [Level]) AS
    (
        SELECT [RoomID], [DateOf], [Segment], 0 AS [Level] 
        FROM @RoomDays AS RD
        UNION ALL 
        SELECT RD1.[RoomID], RD1.[DateOf], RD1.[Segment], [Level] + 1 
        FROM @RoomDays AS RD1
        INNER JOIN DataSource DS
            ON RD1.RoomID = DS.RoomID
        WHERE DATEADD (DAY , 1 , DS.DateOf) =  RD1.DateOf 
    ),
    StartDates AS
    (
        -- Retriving the "Start" records
        SELECT [RoomID], [DateOf], [Segment]
        FROM DataSource
        WHERE [Level] = 0
        EXCEPT
        SELECT [RoomID], [DateOf], [Segment]
        FROM DataSource
        WHERE [Level] = 1
    ),
    TempResult AS
    (
        -- Mathing each "Start" record with its values
        SELECT  SD.[DateOf] AS [StartDate]
               ,RD.[RoomId]
               ,RD.[DateOf]
               ,RD.[Segment]
        FROM StartDates SD
        INNER JOIN @RoomDays RD
            ON SD.RoomID = RD.RoomID
            AND SD.DateOf <= RD.DateOf      
            AND NOT EXISTS (SELECT 1 FROM StartDates WHERE DateOf <= RD.DateOf AND RoomID = RD.RoomID AND SD.DateOf < DateOf)
    )
    SELECT TR.[RoomID]  AS [RoomID]
          ,MIN(TR.[DateOf]) AS [DateFrom]
          ,MAX(TR.[DateOf]) AS [DateThru]
          ,SUBSTRING((SELECT ',' + [Segment] FROM TempResult WHERE [StartDate] = TR.[StartDate] FOR XML PATH('')),2,4000) AS CSV
          ,COUNT(TR.[DateOf]) AS [NumDays]
    FROM TempResult TR
    GROUP BY TR.[RoomID],TR.[StartDate]

SET NOCOUNT OFF
GO

出力:

1   2013-07-03  2013-07-05  1,1,6   3
1   2013-07-15  2013-07-16  6,6 2
2   2013-07-08  2013-07-13  1,1,6,6,1,1 6
3   2013-07-19  2013-07-19  6   1

上記のコードはビューまたは関数に入れることができることに注意してください。または、それを「切り取って」各 CTE の結果を一時テーブルまたはテーブル変数テーブルに保存することもできます。

于 2013-07-10T11:34:15.553 に答える