9

ビジネス作業カレンダーの作業スライスを説明するテーブルがあります: (日付形式は 24 時間形式です)

PK  | STARTDATE          | ENDDATE
__________________________________________
1   | 2012/07/21 02:00   | 2012/07/21 04:00
2   | 2012/07/21 03:00   | 2012/07/21 10:00
3   | 2012/07/21 06:00   | 2012/07/21 17:00
4   | 2012/07/21 18:00   | 2012/07/21 19:00

ここで、次のように (指定された開始日と終了日の範囲内で) 日付範囲をマージしたいと思います。

PK  | STARTDATE          | ENDDATE
__________________________________________
1   | 2012/07/21 02:00   | 2012/07/21 17:00
2   | 2012/07/21 18:00   | 2012/07/21 19:00

SQL97 標準でこれを行う方法はありますか? もしそうなら、他の操作とは何ですか(例えば、逆マージしたい場合、結果は

PK  | STARTDATE          | ENDDATE
__________________________________________
1   | 2012/07/21 00:00   | 2012/07/21 02:00
2   | 2012/07/21 19:00   | 2012/07/22 00:00
4

3 に答える 3

7

SQL Server 構文を使用した例を次に示します。最初に、「先頭」、つまり以前に重複する行がない行を決定します。「ヘッド」の最後の「子」を決定するために、次の「ヘッド」より小さい最後の行を探します。SQLは次のとおりです。

; with  heads as
        (
        select  row_number() over (order by head.StartDate) as PK
        ,       *
        from    YourTable head
        where   not exists 
                (
                select  *
                from    YourTable prev
                where   prev.StartDate < head.StartDate
                        and head.StartDate < prev.EndDate
                )
        )
select  row_number() over (order by h.StartDate) as PK
,       h.StartDate
,       max(yt.EndDate) as EndDate
from    heads h
left join
        heads nh
on      nh.PK = h.PK + 1
left join
        YourTable yt
on      h.StartDate <= yt.StartDate
        and (yt.StartDate < nh.StartDate or nh.StartDate is null)
group by
        h.StartDate

SQL Fiddle での実例。

于 2012-07-25T15:47:37.397 に答える
0

これが私の解決策です。

IF OBJECT_ID('tempdb..#tblDates') IS NOT NULL
    DROP TABLE #tblDates

CREATE TABLE #tblDates (AutoId INT IDENTITY, StartDate DATE, EndDate DATE)

INSERT #tblDates (StartDate, EndDate) SELECT '2014-11-02', '2014-11-08'
INSERT #tblDates (StartDate, EndDate) SELECT '2014-11-07', '2014-11-10'
INSERT #tblDates (StartDate, EndDate) SELECT '2014-11-06', '2014-11-12'

INSERT #tblDates (StartDate, EndDate) SELECT '2014-11-02', '2014-11-15'

INSERT #tblDates (StartDate, EndDate) SELECT '2014-12-10', '2014-12-13'
INSERT #tblDates (StartDate, EndDate) SELECT '2014-12-12', '2014-12-15'
INSERT #tblDates (StartDate, EndDate) SELECT '2014-12-14', '2014-12-16'


-- Optional / Remove the duplicated records of same StartDate and EndDate
DELETE FROM #tblDates WHERE AutoId NOT IN (SELECT MAX(AutoId) FROM #tblDates GROUP BY StartDate, EndDate)

-- Optional / Get only the record with max EndDate grouped by StartDate, Remove Others
DELETE  d1
FROM    #tblDates d1
        JOIN (SELECT x.StartDate, MAX(x.EndDate) MAXEndDate FROM #tblDates x GROUP BY x.StartDate) d2 ON d2.StartDate = d1.StartDate AND d2.MAXEndDate != d1.EndDate

-- Optional / Get only the record with min StartDate grouped by EndDate, Remove Others
DELETE  d1
FROM    #tblDates d1
        JOIN (SELECT x.EndDate, MIN(x.StartDate) MINStartDate FROM #tblDates x GROUP BY x.EndDate) d2 ON d2.EndDate = d1.EndDate AND d2.MINStartDate != d1.StartDate

-- Optional / Remove the overlapping ranges of relevant StartDate and EndDate
DELETE  c
FROM    #tblDates p
        JOIN #tblDates c ON c.AutoId != p.AutoId AND c.StartDate BETWEEN p.StartDate AND p.EndDate AND c.EndDate BETWEEN p.StartDate AND p.EndDate


;WITH Ranges
AS
(
    SELECT  s.StartDate, s.EndDate
    FROM    #tblDates s
            LEFT JOIN #tblDates a ON a.AutoId != s.AutoId AND s.StartDate BETWEEN a.StartDate AND a.EndDate AND s.StartDate != a.StartDate
    WHERE   a.AutoId IS NULL
    UNION ALL
    SELECT  r.StartDate, d.EndDate
    FROM    Ranges r
            JOIN #tblDates d ON r.EndDate != d.EndDate AND r.EndDate BETWEEN d.StartDate AND d.EndDate
)

SELECT StartDate, MAX(EndDate) EndDate FROM Ranges GROUP BY StartDate
于 2014-12-03T07:46:15.980 に答える