1

SQL Fiddle のセットアップ全体: http://sqlfiddle.com/#!4/1fd0e/5

以下に示すように、人のID、レベル、およびレベルの日付範囲を含むデータがあります。

   PID        LVL START_DATE END_DATE

     1          1 01.01.14   19.03.14 
     1          2 20.03.14   15.08.14 
     1          3 16.08.14   09.10.14 
     1          4 10.10.14   31.12.14 
     2          1 01.01.14   31.12.14 
     3          1 01.01.14   16.01.14 

開始日を月の初日に、終了日を月末に設定する必要があります。最終日のルールは、その人物のデータの最終行でない場合にのみ適用されます。

私がこれまでに行ったこと:

select
pid, lvl, 
trunc(start_date, 'month') as start_date,
case when lead(pid, 1) over (PARTITION BY pid order by end_date) is not null 
     then last_day(add_months(end_date, -1)) 
     else last_day(end_date) 
     end as end_date
from date_tbl t;

望ましい出力が得られます:

   PID        LVL START_DATE END_DATE

     1          1 01.01.14   28.02.14 
     1          2 01.03.14   31.07.14 
     1          3 01.08.14   30.09.14 
     1          4 01.10.14   31.12.14 
     2          1 01.01.14   31.12.14 
     3          1 01.01.14   31.01.14 

しかし:それは私のテストデータでうまく機能します。25,000 行以上のデータを含むテーブルの本番データ (魔女は多すぎるデータではありません) では、パフォーマンスが非常に遅くなります。

クエリのパフォーマンスを改善する方法を誰かに教えてもらえますか? たとえば、どの列にどのインデックスを設定しますか...? これまでのところ、インデックス付きの列は PID 列だけです。

4

2 に答える 2

0

実際、私が理解しているように、人のレコードが1つしかない場合、スクリプトは間違った結果を生成します(pid = 3の場合)

お願いします、これを試していただけますか?

select
  pid, 
  lvl, 
  trunc(start_date, 'month') as start_date,
  last_day(add_months(end_date, case when lvl = max(lvl) over (partition by pid) then 0 else -1 end)) end_date
from date_tbl t;

列のインデックスを作成する必要があると思います(pid、lvl desc)

于 2014-04-29T18:36:11.923 に答える