2

特定の期間の売上を表す 10 万行のテーブルがあります。通常、生理は少なくとも数時間続きますが、時折、わずか数分の生理になります。これらの小さな期間は下流のレポートを台無しにするので、前の期間とマージしたいと思います。30 分以下の期間は前の期間とマージされ、販売データが期間全体で合計されます。長い期間の間にゼロ、1 つ、または複数の後続の短い期間がある場合があります。データに時間のギャップはありません。1 つの期間の開始は、前の期間の終了と常に同じです。

このマージを実行するための適切なセットベースの方法 (カーソルなし!) は何ですか?

既存のデータ (簡略化) は次のようになります。

UnitsSold     Start              End
---------------------------------------------------
10            06-12-2013 08:03   06-12-2013 12:07
12            06-12-2013 12:07   06-12-2013 16:05
1             06-12-2013 16:05   06-12-2013 16:09 
1             06-12-2013 16:09   06-12-2013 16:13 
7             06-12-2013 16:13   06-12-2013 20:10

望ましい出力は次のようになります。

UnitsSold     Start              End
---------------------------------------------------
10            06-12-2013 08:03   06-12-2013 12:07
14            06-12-2013 12:07   06-12-2013 16:13
7             06-12-2013 16:13   06-12-2013 20:10

残念ながら、私たちはまだ SQL Server 2008 R2 を使用しているため、SQL Server 2012 の優れた新しいウィンドウ関数を利用することはできません。これにより、この問題を効率的に解決しやすくなる可能性があります。

同様の問題について、SQL で隣接する行をマージするのに良い議論がありますか? . 特に PIVOT/UNPIVOT ソリューションが気に入っていますが、それを自分の問題に適応させる方法に困惑しています。

4

3 に答える 3

1

私の考えは

  1. 長い期間のみのリストを作成する
  2. 「outer apply」で次の長い期間の開始を見つける
  3. サブクエリで単位を合計する

このようなもの

declare @t table (UnitsSold int, start datetime, finish datetime)

insert into @t values (10, '20130612 08:03',   '20130612 12:07')
insert into @t values (12, '20130612 12:07',   '20130612 16:05')
insert into @t values (1, '20130612 16:05',   '20130612 16:09')
insert into @t values (1, '20130612 16:09',   '20130612 16:13')
insert into @t values (7, '20130612 16:13',   '20130612 20:10')

select
    (select SUM(UnitsSold) from @t t3 where t3.start>=t1.start and t3.finish<=ISNULL(oa.start, t1.finish)) as UnitsSold,
    t1.start,
    ISNULL(oa.start, t1.finish) as finish
from @t t1
outer apply (
    select top(1) start
    from @t t2
    where datediff(minute,t2.start, t2.finish)>30 
    and t2.start >= t1.finish
    order by t2.start
) oa
where datediff(minute, t1.start, t1.finish)>30 
于 2013-06-14T06:26:18.440 に答える
0

CTE と累積合計の使用:

DECLARE @t TABLE (UnitsSold INT, Start DATETIME, Finish DATETIME)
INSERT INTO @t VALUES
    (10, '06-12-2013 08:03', '06-12-2013 12:07'),
    (12, '06-12-2013 12:07', '06-12-2013 16:05'),
    (1, '06-12-2013 16:05', '06-12-2013 16:09'),
    (1, '06-12-2013 16:09', '06-12-2013 16:13'),
    (7, '06-12-2013 16:13', '06-12-2013 20:10')

;WITH groups AS (
    SELECT UnitsSold, Start, Finish,
        -- Cumulative sum, IIF returns 1 for each row that
        -- should generate a new row in the final result.
        SUM(IIF(DATEDIFF(MINUTE, Start, Finish) <= 30, 0, 1)) OVER (ORDER BY Start) csum
    FROM @t)

SELECT 
    SUM(UnitsSold) UnitsSold,
    MIN(Start) Start,
    MAX(Finish) Finish
FROM groups
GROUP BY csum
于 2016-08-02T11:56:32.750 に答える