3

2つのテーブルがあります(1つは顧客に送信されたすべてのプログラムの記録を示し、もう1つはユーザーがアクションを実行したすべてのプログラムの記録を示します)。私の最終的な目標は、ユーザーに送信されたプログラムのうち、実行されたプログラムの数を数えることです。私には今それをする方法がありますが、問題があります。プログラムは、1日以内に複数回(例として20を使用します)ユーザーに送信される場合があります。ユーザーが24時間以内にそのプログラムに対してアクションを実行した場合、実行されなかった19個のプログラムと実行された1個のプログラムとしてカウントされたくありません。私はそれを、0が失敗したプログラムに基づいて実行された1としてカウントしたいと思います。

顧客に送信されたプログラムを含むテーブルは、顧客に送信された各プログラムが24時間に1回だけ表示されるように、フィルターで除外する必要があります。

私の解決策は、「ウィンドウ」タイプのものを使用して、プログラムが顧客に送信されると、その顧客に対して24時間「ロック」され、「顧客に送信されたプログラム」クエリに複数回表示されないようにすることです。 。

私はこのようなテーブルを持っています:

Customer    Time    Program
-----------------------------------
1           8:05    a
1           10:30   a
1           11:30   a
1           12:30   b
1           1:25    a
2           9:38    b
2           10:38   c
2           1:36    c
2           2:40    c
2           3:41    b
.
.
.

特定の時間枠内に顧客ごとに重複するプログラムを削除するテーブル(削除ではなくクエリ)を取得したい(混乱します!私は知っています)

これが私が欲しいものです(たとえば、3時間の時間枠で):

Customer    Time    Program
-----------------------------------
1           8:05    a
1           11:30   a
1           12:30   b
2           9:38    b
2           10:38   c
2           2:40    c
2           3:41    b
.
.
.
4

2 に答える 2

2

これを試して:

select *
from t
where not exists (select 1 from t t2
                  where t2.customer = t.customer and
                        t2.program = t.program and
                        t2.time - t.time < 3.0/24 and
                        t2.time > t.time
                 )

日時演算はデータベースに依存しますが、これは多くのデータベースで機能します。

于 2013-02-21T15:34:03.287 に答える
1

あなたが言っていることは、再帰クエリで(のみ)解決できると思います。解決策は次のとおりです。

WITH cte AS
  ( SELECT 
        customer, program, time,
        ROW_NUMBER() 
            OVER (PARTITION BY customer, program
                  ORDER BY time)
          AS rn, 
        MIN(time) 
            OVER (PARTITION BY customer, program
                  ORDER BY time 
                  RANGE BETWEEN 3.0/24 FOLLOWING 
                            AND UNBOUNDED FOLLOWING)
          AS next_time
    FROM a
  )

SELECT 
    customer, time, program
FROM 
    cte
START WITH rn = 1
CONNECT BY PRIOR customer = customer
       AND PRIOR program = program
       AND PRIOR next_time = time
ORDER BY 
    customer, time, program ;

上記に置き換えMIN(time)てもFIRST_VALUE(time)同じ結果が得られます。それはより効率的かもしれません。

SQL-Fiddleでテスト済み

大きなテーブルでの効率はおそらくあまり良くないでしょう。より小さなデータセットでクエリを実行してみることができます。

そして、少なくともこのインデックスを追加して、インデックススキャンを実行する必要があります。

CREATE INDEX ix                -- choose a name for the index
  ON tableX                    -- the table name
  (customer, program, time) ;

また、最終的な順序をスキップするか、使用されているインデックスにより類似するように変更することもできます。

ORDER BY 
    customer, program, time ;
于 2013-02-21T17:07:55.890 に答える