6

イースター島1で、世界で最後に残っているユニコーンを観察している多くの研究者がいます。研究者は毎日、どのユニコーンを目撃したか、目撃した日付、それぞれのユニコーンの赤ちゃんの数、目撃時に酔っていたかどうかを記録します。これらは中央の場所に個別にアップロードされ、毎日すべての新しい観測結果のフラット ファイルが送信されます。

情報を含む次のようなテーブルがあります。

create table unicorn_observations (
     observer_id number not null
   , unicorn_id number not null
   , created date not null -- date the record was inserted into the database
   , lastseen date not null -- date the record was last seen
   , observation_date date not null
   , no_of_babies number not null
   , drunk varchar2(1) not null
   , constraint pk_uo primary key ( observer_id, unicorn_id, created )
   , constraint chk_uo_babies check ( no_of_babies >= 0 )
   , constraint chk_uo_drunk check ( drunk in ('y','n') )
     );

observer_idテーブルは、unicorn_idobservation_dateまたはで個別に一意 lastseenです。

時々、データの出力を管理するCobold [sic] が少し間違って、同じデータを 2 回再出力することがあります。この状況ではlastseen、新しいレコードを作成する代わりに更新します。これは、すべての列が同じである場合にのみ行います

残念ながら、研究者は第 3 正規形を完全には認識していません。毎月、新しい観測が行われていない場合でも、いくつかのユニコーンの前月の観測をアップロードします。これはnew observation_dateで行います。つまり、新しいレコードがテーブルに挿入されます。

研究者がいくつかの観察を遅れて提出することがあるので、私は完全な追跡可能性のために別のものを持っていcreatedます。lastseenこれらはデータベースによって作成され、提出された情報の一部ではありません。

サンプル データを次に示します (スクロール バーなしで収まるように、列名を部分的に変更しています)。

+--------+--------+----------+-----------+--------- --+---------+-------+
| | OBS_ID | UNI_ID | 作成されました | 最後に見た | OBS_DATE | #赤ちゃん | 酔っ払い |
+--------+--------+----------+-----------+--------- --+---------+-------+
| | 1 | 1 | 2011 年 11 月 1 日 | 2011 年 11 月 1 日 | 2011 年 10 月 31 日 | 10 | n |
| | 1 | 2 | 2011 年 11 月 1 日 | 2011 年 11 月 1 日 | 2011 年 10 月 31 日 | 10 | n |
| | 1 | 3 | 2011 年 11 月 1 日 | 2011 年 11 月 1 日 | 2011 年 10 月 31 日 | 10 | n |
| | 1 | 6 | 2011 年 11 月 10 日 | 2011 年 11 月 10 日 | 2011 年 11 月 7 日 | 0 | n |
| | 1 | 1 | 2011 年 11 月 17 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n |
| | 1 | 2 | 2011 年 11 月 17 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n |
| | 1 | 3 | 2011 年 11 月 17 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n |
| | 1 | 6 | 2011 年 11 月 17 日 | 2011 年 11 月 17 日 | 2011 年 11 月 17 日 | 0 | n |
| | 1 | 6 | 2011 年 12 月 1 日 | 2011 年 12 月 1 日 | 2011 年 12 月 1 日 | 0 | n |
| | 1 | 6 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 3 | n |
| | 1 | 6 | 2012 年 2 月 1 日 | 2012 年 2 月 1 日 | 2012 年 2 月 1 日 | 0 | n |
| | 1 | 6 | 2012 年 3 月 1 日 | 2012 年 3 月 1 日 | 2012 年 3 月 1 日 | 0 | n |
| | 1 | 6 | 2012 年 4 月 1 日 | 2012 年 4 月 1 日 | 2012 年 4 月 1 日 | 0 | n |
| | 1 | 1 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y |
| | 1 | 2 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y |
| | 1 | 3 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y |
| | 1 | 6 | 2012 年 5 月 1 日 | 2012 年 5 月 1 日 | 2012 年 5 月 1 日 | 0 | n |
+--------+--------+----------+-----------+--------- --+---------+-------+

これらの観測結果を部分的に非正規化して、新しいレコードが同じobserver_idunicorn_idno_of_babiesおよびdrunk(ペイロード)で受信された場合、新しいレコードを挿入する代わりに、テーブルの新しい observation_date列を更新するようにしたいと思います。この状況でlast_observation_dateも更新します。lastseen

このテーブルに参加する複雑なユニコーン関連のクエリが多数あるため、これを行う必要があります。研究者は月に約 1000 万回、新しい日付の古い観測をアップロードし、私は月に約 900 万の真に新しい記録を受け取ります。私は 1 年間ランニングを続けており、すでに 225m のユニコーンを観測しています。各ペイロードの組み合わせの最後の観測日を知る必要があるだけなので、テーブルのサイズを大幅に縮小し、フルスキャンに多くの時間を節約したいと考えています。

これは、テーブルが次のようになることを意味します。

create table unicorn_observations (
     observer_id number not null
   , unicorn_id number not null
   , created date not null -- date the record was inserted into the database
   , lastseen date not null -- date the record was last seen
   , observation_date date not null
   , no_of_babies number not null
   , drunk varchar2(1) not null
   , last_observation_date date
   , constraint pk_uo primary key ( observer_id, unicorn_id, created )
   , constraint chk_uo_babies check ( no_of_babies >= 0 )
   , constraint chk_uo_drunk check ( drunk in ('y','n') )
     );

テーブルに格納されたデータは次のようになります。last_observation_date観測が一度だけ「見られた」場合は、 nullかどうかは関係ありません。現在のテーブルを部分的に非正規化してこのようにするだけで、データの読み込みに助けは必要ありません。

+--------+--------+----------+-----------+--------- --+---------+-------+-------------+
| | OBS_ID | UNI_ID | 作成されました | 最後に見た | OBS_DATE | #赤ちゃん | 酔っ払い | LAST_OBS_DT |
+--------+--------+----------+-----------+--------- --+---------+-------+-------------+
| | 1 | 6 | 2011 年 11 月 10 日 | 2011 年 12 月 1 日 | 2011 年 11 月 7 日 | 0 | n | 2011 年 12 月 1 日 |
| | 1 | 1 | 2011 年 11 月 1 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n | 2011 年 10 月 31 日 |
| | 1 | 2 | 2011 年 11 月 1 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n | 2011 年 10 月 31 日 |
| | 1 | 3 | 2011 年 11 月 1 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n | 2011 年 10 月 31 日 |
| | 1 | 6 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 3 | n | | |
| | 1 | 6 | 2012 年 2 月 1 日 | 2012 年 5 月 1 日 | 2012 年 2 月 1 日 | 0 | n | 2012 年 5 月 1 日 |
| | 1 | 1 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y | | |
| | 1 | 2 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y | | |
| | 1 | 3 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y | | |
+--------+--------+----------+-----------+--------- --+---------+-------+-------------+

明白な答え

select observer_id as obs_id
     , unicorn_id as uni_id
     , min(created) as created
     , max(lastseen) as lastseen
     , min(observation_date) as obs_date
     , no_of_babies as "#BABIES"
     , drunk
     , max(observation_date) as last_obs_date
  from unicorn_observations
 group by observer_id
        , unicorn_id
        , no_of_babies
        , drunk

2012 年1月1 日のユニコーン 6 の 3 つのユニコーンの赤ちゃんの単一の観察を無視するため、機能しません。これは、11 月 10 日に作成されたレコードの が正しくないことを意味lastseenます。

+--------+--------+----------+-----------+--------- --+---------+-------+-------------+
| | OBS_ID | UNI_ID | 作成されました | 最後に見た | OBS_DATE | #赤ちゃん | 酔っ払い | LAST_OBS_DT |
+--------+--------+----------+-----------+--------- --+---------+-------+-------------+
| | 1 | 1 | 2011 年 11 月 1 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n | 2011 年 10 月 31 日 |
| | 1 | 2 | 2011 年 11 月 1 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n | 2011 年 10 月 31 日 |
| | 1 | 3 | 2011 年 11 月 1 日 | 2011 年 11 月 17 日 | 2011 年 4 月 9 日 | 10 | n | 2011 年 10 月 31 日 |
| | 1 | 6 | 2011 年 11 月 10 日 | 2012 年 5 月 1 日 | 2011 年 11 月 7 日 | 0 | n | 2012 年 5 月 1 日 |
| | 1 | 6 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 3 | n | 2012 年 1 月 1 日 |
| | 1 | 1 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y | 2012 年 4 月 19 日 |
| | 1 | 2 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y | 2012 年 4 月 19 日 |
| | 1 | 3 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 2012 年 4 月 19 日 | 7 | y | 2012 年 4 月 19 日 |
+--------+--------+----------+-----------+--------- --+---------+-------+-------------+

私は現在、いくつかの手続き型ロジック、つまりループなしでこれを行う方法を見ていません。created225m 行のテーブルを 260 回 (個別の日付の数) フルスキャンする必要があるため、この状況でのループは避けたいと思います。lag()andを使用してもlead()、ユニコーンごとに不確定な量の観測があるため、再帰的である必要があります。

単一の SQL ステートメントでこのデータセットを作成する方法はありますか?

テーブル仕様とサンプル データもSQL Fiddleにあります。


より良い説明を試みました:

問題は、何かが真実だったときを維持することです。2012 年 1 月 1 日、ユニコーン 6 に 3 人の赤ちゃんが生まれました。

GROUP BY によって作成された「テーブル」で unicorn 6 だけを見てみます。1月1 日の赤ちゃんの数を調べようとすると、矛盾する 2 つのレコードが返されます。

+--------+--------+----------+-----------+--------- --+---------+-------+-------------+
| | OBS_ID | UNI_ID | 作成されました | 最後に見た | OBS_DATE | #赤ちゃん | 酔っ払い | LAST_OBS_DT |
+--------+--------+----------+-----------+--------- --+---------+-------+-------------+
| | 1 | 6 | 2011 年 11 月 10 日 | 2012 年 5 月 1 日 | 2011 年 11 月 7 日 | 0 | n | 2012 年 5 月 1 日 |
| | 1 | 6 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 3 | n | 2012 年 1 月 1 日 |
+--------+--------+----------+-----------+--------- --+---------+-------+-------------+

ただし、2 番目のテーブルのように、1 行だけが必要です。ここでは、ユニコーン 6 の赤ちゃんが 0 だった 2 つの期間が、3 だった日によって 2 つの行に分けられているため、任意の時点で最大 1 つの「正しい」値があります。

+--------+--------+----------+-----------+--------- --+---------+-------+-------------+
| | OBS_ID | UNI_ID | 作成されました | 最後に見た | OBS_DATE | #赤ちゃん | 酔っ払い | LAST_OBS_DT |
+--------+--------+----------+-----------+--------- --+---------+-------+-------------+
| | 1 | 6 | 2011 年 11 月 10 日 | 2011 年 12 月 1 日 | 2011 年 11 月 7 日 | 0 | n | 2011 年 12 月 1 日 |
| | 1 | 6 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 2012 年 1 月 1 日 | 3 | n | | |
| | 1 | 6 | 2012 年 2 月 1 日 | 2012 年 5 月 1 日 | 2012 年 2 月 1 日 | 0 | n | 2012 年 5 月 1 日 |
+--------+--------+----------+-----------+--------- --+---------+-------+-------------+

1.モアイの周りで放牧

4

3 に答える 3

2

これを試して。

with cte as
(
    select v.*,  ROW_NUMBER() over (partition by grp, unicorn_id order by grp, unicorn_id) rn
    from
    (
        select u.*, 
            ROW_NUMBER() over (partition by unicorn_id order by no_of_babies, drunk, created )
            -ROW_NUMBER() over (partition by unicorn_id order by created) as grp
        from unicorn_observations u
    ) v
) 
    select 
        observer_id, cte.unicorn_id, mincreated,maxlastseen,minobsdate,no_of_babies,drunk,maxobsdate
    from cte 
        inner join 
        (    
            select 
                unicorn_id, grp, 
                min(created) as mincreated,
                max(lastseen) as maxlastseen, 
                min(observation_date) as minobsdate,
                max(observation_date) as maxobsdate
            from cte 
            group by unicorn_id, grp
        ) v
        on cte.grp = v.grp
        and cte.unicorn_id = v.unicorn_id
    where rn=1  
    order by created;
于 2012-10-04T10:31:19.650 に答える
1

あなたがやろうとしていること、主にユニコーン 6 の特定の問題に関する最新情報に基づいて、これはあなたが望む結果をもたらすと思います。再帰的な and は必要ありませんがleadlag2 つのレベルが必要です。

select *
from (
    select observer_id, unicorn_id,
        case when first_obs_dt is null then created
            else lag(created) over (order by rn) end as created,
        case when last_obs_dt is null then lastseen
            else lead(lastseen) over (order by rn) end as lastseen,
        case when first_obs_dt is null then observation_date
            else lag(observation_date) over (order by rn)
            end as observation_date,
        no_of_babies,
        drunk,
        case when last_obs_dt is null then observation_date
            else null end as last_obs_dt
    from (
        select observer_id, unicorn_id, created, lastseen, 
            observation_date, no_of_babies, drunk,
            case when lag_no_babies != no_of_babies or lag_drunk != drunk
                or lag_obs_dt is null then null
                else lag_obs_dt end as first_obs_dt,
            case when lead_no_babies != no_of_babies or lead_drunk != drunk
                or lead_obs_dt is null then null
                else lead_obs_dt end as last_obs_dt,
            rownum rn
        from (
            select observer_id, unicorn_id, created, lastseen,
                observation_date, no_of_babies, drunk,
                lag(observation_date)
                    over (partition by observer_id, unicorn_id, no_of_babies,
                            drunk
                        order by observation_date) lag_obs_dt,
                lag(no_of_babies)
                    over (partition by observer_id, unicorn_id, drunk
                        order by observation_date) lag_no_babies,
                lag(drunk)
                    over (partition by observer_id, unicorn_id, no_of_babies
                        order by observation_date) lag_drunk,
                lead(observation_date)
                    over (partition by observer_id, unicorn_id, no_of_babies,
                        drunk
                    order by observation_date) lead_obs_dt,
                lead(no_of_babies)
                    over (partition by observer_id, unicorn_id, drunk
                        order by observation_date) lead_no_babies,
                lead(drunk)
                    over (partition by observer_id, unicorn_id, no_of_babies
                        order by observation_date) lead_drunk
            from unicorn_observations
            order by 1,2,5
        )
    )
    where first_obs_dt is null or last_obs_dt is null
)
where last_obs_dt is not null
order by 1,2,3,4;

これにより、次のことが得られます。

OBSERVER_ID UNICORN_ID CREATED   LASTSEEN  OBSERVATI NO_OF_BABIES D LAST_OBS_
----------- ---------- --------- --------- --------- ------------ - ---------
          1          1 17-NOV-11 01-NOV-11 09-APR-11           10 n 31-OCT-11
          1          1 19-APR-12 19-APR-12 19-APR-12            7 y 19-APR-12
          1          2 17-NOV-11 01-NOV-11 09-APR-11           10 n 31-OCT-11
          1          2 19-APR-12 19-APR-12 19-APR-12            7 y 19-APR-12
          1          3 17-NOV-11 01-NOV-11 09-APR-11           10 n 31-OCT-11
          1          3 19-APR-12 19-APR-12 19-APR-12            7 y 19-APR-12
          1          6 10-NOV-11 01-DEC-11 07-NOV-11            0 n 01-DEC-11
          1          6 01-JAN-12 01-JAN-12 01-JAN-12            3 n 01-JAN-12
          1          6 01-FEB-12 01-MAY-12 01-FEB-12            0 n 01-MAY-12

9 rows selected.

ユニコーン 6 の 3 つのレコードがありlastseenますobservation_dateが、3 番目の と はあなたのサンプルとは逆なので、まだ理解していないかどうかはわかりません。observation_date新しいレコードを追加するときに何が起こるかという理由で、各グループ内で最も古いものと最新のものを保持したいと考えていますlastseenが、よくわかりません...

そのため、最も内側のクエリは、テーブルから生データを取得し、わずかに異なるパーティションを使用して、 および および 列のandlead取得lagします。は、後で使用できるように、次のステップで取得し、次のステップでの注文に使用できます。簡潔にするためにユニコーン6の場合:observation_date no_of_babiesdrunkorder byrownum

CREATED   LASTSEEN  OBSERVATI NO_OF_BABIES D LAG_OBS_D LAG_NO_BABIES L LEAD_OBS_ LEAD_NO_BABIES L
--------- --------- --------- ------------ - --------- ------------- - --------- -------------- -
10-NOV-11 10-NOV-11 07-NOV-11            0 n                           17-NOV-11              0 n
17-NOV-11 17-NOV-11 17-NOV-11            0 n 07-NOV-11             0 n 01-DEC-11              0 n
01-DEC-11 01-DEC-11 01-DEC-11            0 n 17-NOV-11             0 n 01-FEB-12              3 n
01-JAN-12 01-JAN-12 01-JAN-12            3 n                       0                          0
01-FEB-12 01-FEB-12 01-FEB-12            0 n 01-DEC-11             3 n 01-MAR-12              0 n
01-MAR-12 01-MAR-12 01-MAR-12            0 n 01-FEB-12             0 n 01-APR-12              0 n
01-APR-12 01-APR-12 01-APR-12            0 n 01-MAR-12             0 n 01-MAY-12              0 n
01-MAY-12 01-MAY-12 01-MAY-12            0 n 01-APR-12             0 n

次のレベルでは、 orの値のいずれかが変更された場合、 leadandのlag値が空白になります。具体的には、赤ちゃんの数での分割についてのみ言及しましたが、飲酒についても分割したいと思います。この後、 orのいずれかを持つものは、ミニ範囲の開始または終了です。observation_datenum_of_babiesdrunknullfirst_obs_datelast_obs_date

CREATED   LASTSEEN  OBSERVATI NO_OF_BABIES D FIRST_OBS LAST_OBS_         RN
--------- --------- --------- ------------ - --------- --------- ----------
10-NOV-11 10-NOV-11 07-NOV-11            0 n           17-NOV-11          1
17-NOV-11 17-NOV-11 17-NOV-11            0 n 07-NOV-11 01-DEC-11          2
01-DEC-11 01-DEC-11 01-DEC-11            0 n 17-NOV-11                    3
01-JAN-12 01-JAN-12 01-JAN-12            3 n                              4
01-FEB-12 01-FEB-12 01-FEB-12            0 n           01-MAR-12          5
01-MAR-12 01-MAR-12 01-MAR-12            0 n 01-FEB-12 01-APR-12          6
01-APR-12 01-APR-12 01-APR-12            0 n 01-MAR-12 01-MAY-12          7
01-MAY-12 01-MAY-12 01-MAY-12            0 n 01-APR-12                    8

値が前または後の値と同じか、それらに取って代わられるため、ミニ範囲の開始または終了ではないものはすべて無視できるようになりました。これは、不確定な観測数の問題を扱います。この時点で無視する数は問題ではありません。first_obs_dtしたがって、次のレベルでは、とlast_obs_dtの両方が null でない行をフィルタリングすることにより、これらの中間値を排除します。そのフィルタリングされたセット内には、各日付の最初または最後の値を取得するためのleadとの 2 番目のレイヤーがありlagます。

CREATED   LASTSEEN  OBSERVATI NO_OF_BABIES D LAST_OBS_
--------- --------- --------- ------------ - ---------
10-NOV-11 01-DEC-11 07-NOV-11            0 n
10-NOV-11 01-DEC-11 07-NOV-11            0 n 01-DEC-11
01-JAN-12 01-JAN-12 01-JAN-12            3 n 01-JAN-12
01-FEB-12 01-MAY-12 01-FEB-12            0 n
01-FEB-12 01-MAY-12 01-FEB-12            0 n 01-MAY-12

最後に、a を持たない残りの行last_obs_dtが除外されます。

今、私が誤解したビットを確認するのを待ちます... *8-)


修正leadlag注文に続いて、ユニコーン 1 の各ステージの同じ情報:

CREATED   LASTSEEN  OBSERVATI NO_OF_BABIES D LAG_OBS_D LAG_NO_BABIES L LEAD_OBS_ LEAD_NO_BABIES L
--------- --------- --------- ------------ - --------- ------------- - --------- -------------- -
17-NOV-11 17-NOV-11 09-APR-11           10 n                           31-OCT-11             10 n
01-NOV-11 01-NOV-11 31-OCT-11           10 n 09-APR-11            10 n
19-APR-12 19-APR-12 19-APR-12            7 y

CREATED   LASTSEEN  OBSERVATI NO_OF_BABIES D FIRST_OBS LAST_OBS_         RN
--------- --------- --------- ------------ - --------- --------- ----------
17-NOV-11 17-NOV-11 09-APR-11           10 n           31-OCT-11          1
01-NOV-11 01-NOV-11 31-OCT-11           10 n 09-APR-11                    2
19-APR-12 19-APR-12 19-APR-12            7 y                              3

CREATED   LASTSEEN  OBSERVATI NO_OF_BABIES D LAST_OBS_
--------- --------- --------- ------------ - ---------
17-NOV-11 17-NOV-11 09-APR-11           10 n 09-APR-11
19-APR-12 19-APR-12 19-APR-12            7 y 19-APR-12

保存されたデータがどうなるのか、元のデータがこのように順不同observation_datelastseen入力されたとき、または将来追加された新しいレコードでその状況で何をするのかわかりません。

于 2012-10-04T22:53:14.757 に答える
0

このタイプの問題は、最初にサブクエリでいくつかのフラグを作成し、次にそれらを使用することで解決できます。

with obs_flags as (
    select 
       observer_id as obs_id
     , unicorn_id as uni_id
     , case when lag(observation_date) over (
           partition by unicorn_id, no_of_babies, drunk
           order by unicorn_id, observation_date
       ) is null then 1 else 0 end as group_start
     , case when lead(observation_date) over (
           partition by unicorn_id, no_of_babies,drunk
           order by unicorn_id, observation_date
       ) is null then 1 else 0 end as group_end
     , observation_date
     , no_of_babies
     , drunk
     , lastseen
     , created
  from unicorn_observations
)
select obs_start.obs_id
     , obs_start.uni_id
     , obs_start.created
     , obs_end.lastseen as lastseen
     , obs_start.observation_date
     , obs_start.no_of_babies as "#BABIES"
     , obs_start.drunk
     , obs_end.observation_date as last_obs_date
  from obs_flags obs_start
  join obs_flags obs_end on 
      obs_start.group_start = 1 and
      obs_end.group_end = 1 and
      obs_start.uni_id = obs_end.uni_id and
      obs_start.no_of_babies = obs_end.no_of_babies and
      obs_start.drunk = obs_end.drunk and
      obs_start.observation_date <= obs_end.observation_date and
      --Only join with the first end point we find:
      not exists (
          select * from obs_flags f where
              obs_start.uni_id = f.uni_id and
              obs_start.no_of_babies = f.no_of_babies and
              obs_start.drunk = f.drunk and
              f.group_end = 1 and
              f.observation_date < obs_end.observation_date and
              f.observation_date >= obs_start.observation_date
      );

これは複雑な問題です。私はあなたの要件を完全に満たしていない可能性があります(またはタイプミスがある可能性があります。テストするOracleがありません)。ただし、それを行う方法についてのアイデアを提供する必要があります。

基本的に、最初に関心のある期間のすべての開始レコードと終了レコードを検索します。次に、同じグループ内で各開始レコードを次の終了レコードに結合します。

更新:私の元のコードは、開始後に終了が来たことを確認しませんでした。私はそれを修正しました。

Update2: Ben が指摘したように、ここではnot exists句が遅くなります。過去に私が物事をスピードアップするのに役立った別の方法は、これを 2 つのステップで行うことです。最初にすべての潜在的なペアリングを見つけ、次にその中から正しいペアリングのみを個別に選択します。

この場合、一時テーブルまたはサブクエリで、それぞれobs_startを潜在的に正しいすべてに結合しますobs_end

次に、これらの組み合わせの中から、obs_endそれぞれの最も早いものを選択しますobs_start

于 2012-10-04T09:46:03.533 に答える