3

これは奇妙な質問です。それがかなり実行可能かどうかはわかりません。

次のテーブルがあるとしましょう:

person | product  | trans  | purchase_date
-------+----------+--------+---------------
jim    | square   | aaaa   | 2013-03-04 00:01:00
sarah  | circle   | aaab   | 2013-03-04 00:02:00
john   | square   | aac1   | 2013-03-04 00:03:00
john   | circle   | aac2   | 2013-03-04 00:03:10
jim    | triangle | aad1   | 2013-03-04 00:04:00
jim    | square   | abcd   | 2013-03-04 00:05:00
sarah  | square   | efgh   | 2013-03-04 00:07:00
jim    | circle   | ijkl   | 2013-03-04 00:22:00
sarah  | circle   | mnop   | 2013-03-04 00:24:00
sarah  | square   | qrst   | 2013-03-04 00:26:00
sarah  | circle   | uvwx   | 2013-03-04 00:44:00

四角形と円 (または円と四角形) の購入の差がいつ 10 分を超えたかを知る必要があります。理想的には、その違いも知りたいのですが、それは必須ではありません。

その結果、ここに私が必要なものがあります:

person | product  | trans  | purchase_date
-------+----------+--------+---------------
jim    | square   | abcd   | 2013-03-04 00:05:00
jim    | circle   | ijkl   | 2013-03-04 00:22:00
sarah  | square   | efgh   | 2013-03-04 00:07:00
sarah  | circle   | mnop   | 2013-03-04 00:24:00
sarah  | square   | qrst   | 2013-03-04 00:26:00
sarah  | circle   | uvwx   | 2013-03-04 00:44:00

これは毎日実行されるため、「where」句を追加して、クエリが手に負えないようにします。また、複数のトランザクションが表示される可能性があることも承知しています (たとえば、サークルの購入に 20 分、次にスクエアの購入に 20 分、次にサークルの購入に 20 分かかるとします。つまり、時間差が発生する 2 つのインスタンスがあったことになります)。 10分以上かかりました)。

何かアドバイス?私はpostgres 8.1.23を使用しています

4

3 に答える 3

1

現代のソリューション

現代の Postgres (8.4 以降) では、ウィンドウ関数row_number()を使用して、グループごとに連続した番号を取得できます。次に、前の行と次の行に左結合して、それらのいずれかが基準に一致するかどうかを確認できます。出来上がり。

WITH x AS (
   SELECT *
         ,row_number() OVER (PARTITION BY person ORDER BY purchase_date) AS rn
   FROM   tbl
   WHERE  product IN ('circle', 'square')
   )
SELECT x.person, x.product, x.trans, x.purchase_date
FROM   x
LEFT   JOIN x y ON y.person = x.person AND y.rn = x.rn + 1
LEFT   JOIN x z ON z.person = x.person AND z.rn = x.rn - 1
WHERE (y.product <> x.product
       AND y.purchase_date > x.purchase_date + interval '10 min')
   OR (z.product <> x.product
       AND z.purchase_date < x.purchase_date - interval '10 min')
ORDER  BY x.person, x.purchase_date;

SQLフィドル。

Postgres 8.1 のソリューション

Postgres 8.1 でこれをテストすることはできません。生き残ったインスタンスは利用できません。v8.4 でテスト済みで動作します一時シーケンスと一時テーブルおよび とCREATE TABLE ASは、既に使用可能でした。
一時的なシーケンスとテーブルは自分だけが見ることができるため、同時クエリでも連続した数値を取得できます。

CREATE TEMP SEQUENCE s;

CREATE TEMP TABLE x AS
SELECT *, nextval('s') AS rn  -- get row-numbers from sequence
FROM  (
   SELECT *
   FROM   tbl
   WHERE  product IN ('circle', 'square')
   ORDER  BY person, purchase_date  -- need to order in a subquery first!
   ) a;

その後、SELECT上記と同じように動作するはずです:

SELECT x.person, x.product, x.trans, x.purchase_date
FROM   x
LEFT   JOIN x y ON y.person = x.person AND y.rn = x.rn + 1
LEFT   JOIN x z ON z.person = x.person AND z.rn = x.rn - 1
WHERE (y.product <> x.product
       AND y.purchase_date > x.purchase_date + interval '10 min')
   OR (z.product <> x.product
       AND z.purchase_date < x.purchase_date - interval '10 min')
ORDER  BY x.person, x.purchase_date;
于 2013-03-05T04:56:20.850 に答える
0

--想定

  1. 即日購入分の差額を知りたい。日付が重要でない場合は、where 句を削除します。
  2. 購入日より前ではなく、その後に円を正方形にすることのみを検討してください。.

.

SELECT A.person, A.product, a.Trans, A.Purchase_date, B.Purchase_date, 
hours_diff * 60 + DATE_PART('minute', B.purchase_date - A.Purchase_date ) as minuteDifference
FROM yourTable A
LEFT JOIN yourTable B 
  on A.person = B.Person 
    and ((A.product = 'square' and b.product = 'circle') 
      OR (A.Product = 'circle' and b.product = 'square'))
    and A.purchase_date <= B.Purchase_date
WHERE (A.purchase_Date::date = B.purchase_date::date OR B.purchase_date is null)

Null B.purchase_dates は、円/正方形または正方形の円の組み合わせがない場合に通知します。

于 2013-03-04T19:02:00.087 に答える
0

次のような「ON」句を使用して、テーブルをそれ自体に結合してみてください。

SELECT a.Person, CAST((DATEDIFF(mi, b.purchaseDateb a.purchaseDate)/60.0) AS Decimal) AS TimeDiff, a.Product, b.Product FROM <TABLE> a
JOIN <TABLE> b
ON a.Person = b.Person AND b.purchaseDate > a.purchaseDate
WHERE
(a.Product = 'Circle' AND b.Product = 'Square')
OR
(a.Product = 'Square' AND b.Product = 'Circle')

テーブルをそれ自体に結合すると、同じ人による 2 つの購入を組み合わせた行が得られます。「b.purchaseDate > a.purchaseDate」に制限することで、行がそれ自体に一致するのを防ぎます。次に、購入したさまざまな製品を簡単に確認できます。

時差は最後のトリッキーな部分です。上記の内容は、ここで見つけた回答に基づいています。動作するはずです。この出力がうまくいかない場合に使用できるバリエーションがいくつかあります。

同じ DATEDIFF 関数を使用して 10 分を超える時間をテストする句を WHERE ステートメントに追加する必要がありますが、これは大きな課題にはなりません。

これは、質問にあるものと正確に一致しないことに注意してください。これには、ジムの最初のトランザクションの行と、ジムの 2 回目の購入の行が含まれます。どちらも同じ円に一致し、両方の時間 (ijkl-abcd AND ijkl-aaaa) が得られます。これを指摘してくれた xQbert のコメントに感謝します。

于 2013-03-04T18:46:11.207 に答える