1

次のようなPostgresテーブルにいくつかのデータがあります。

1 apple datetime1
2 orange datetime2
3 apple datetime3
4 orange datetime4
5 apple datetime5
6 orange datetime6
.

日時は常に昇順であり、ほとんどの場合、リンゴの行が最初に挿入され、オレンジ色の行が 2 番目に挿入されますが、いくつかの例外をキャッチして排除する必要があります。

実際に必要なのは、リンゴとオレンジのみをペアにする Postgres クエリです。

1 apple datetime1 2 orange datetime2
3 apple datetime3 4 orange datetime4
5 apple datetime5 6 orange datetime6

リンゴは他のリンゴと決して組み合わせてはならず、オレンジは他のオレンジと組み合わせてはいけません.

いくつかの条件があります:

1) 新しく生成された行では、apple が常に 1 番目で、orange が 2 番目になります。

2) リンゴとオレンジの行を常に最も近い日時とペアにし、他の行を無視します。

たとえば、元のデータが次のようになっているとします。

1 apple datetime1
2 apple datetime2
3 orange datetime3
4 orange datetime4

ペア

2 apple datetime2 3 orange datetime3

行を無視する

1 apple datetime1
4 orange datetime4

Postgresでこれを行う方法はありますか?

4

4 に答える 4

2

日時は常に昇順であり、ほとんどの場合、リンゴの行が最初に挿入され、オレンジ色の行が 2 番目に挿入されますが、いくつかの例外をキャッチして排除する必要があります。

私の理解が正しければ、同じ果物の列が 2 つ連続しているかどうかを調べたいと思いますよね?

もしそうなら、あなたは次のようにすることができます:

WITH Q AS (
    SELECT *, ROW_NUMBER() OVER (ORDER BY datetime) R
    FROM YOUR_TABLE
)
SELECT *
FROM Q Q1 JOIN Q Q2 ON Q1.R = Q2.R - 1
WHERE Q1.fruit = Q2.fruit;

平易な英語で: すべての行を次の行と結合し (「次」の意味はdatetime順序によって決まります)、それらの結果が一致するかどうかを確認します。このSQL Fiddleでそれを試すことができます。

ところで、これは良いデータベース設計ではありません。上記の「無効な」状況がデータベース構造自体によって自然に防止されるように、再設計を検討する必要があります。

于 2012-06-04T16:07:32.503 に答える
1

CTE & ウィンドウ関数を使用したソリューション:

WITH x AS (
    SELECT *
          ,lead(tbl) OVER (ORDER BY id) AS y
    FROM tbl
    )
SELECT x.id,     x.fruit,   x.dt
     , (y).id, (y).fruit, (y).dt
FROM   x
WHERE  fruit = 'apple'
AND    (y).fruit = 'orange'
ORDER  BY x.id;

サブクエリとしても同様に実行できますが、 @wildplasser からのリクエストごとです。:)

ウィンドウ関数ごとに「次の」行全体を選択しますlead()。複合 (行) タイプの列にアクセスするための括弧付きの構文に注意してくださいy

于 2012-06-04T15:49:40.013 に答える
0
select 
    t0.id, t0.fruit, t0.datetime, 
    t1.id, t1.fruit, t1.datetime
from t t0
inner join t t1 on 
    t0.fruit = 'apple' 
    and 
    t1.fruit = 'orange'
    and
    t0.datetime < t1.datetime
order by t1.datetime - t0.datetime
limit 1
于 2012-06-04T15:28:34.137 に答える
0
SET search_path='lutser';

DROP TABLE fruits;
CREATE TABLE fruits
    ( id INTEGER NOT NULL
    , fruit varchar
    , zdate varchar
    );  
INSERT INTO fruits(id,fruit,zdate)
VALUES

(1, 'apple', 'datetime01')
, (2, 'orange', 'datetime02')
, (3, 'apple', 'datetime03')
, (4, 'orange', 'datetime04')
, (5, 'apple', 'datetime05')
, (6, 'orange', 'datetime06')
, (11, 'apple', 'datetime11')
, (12, 'apple', 'datetime12')
, (13, 'orange', 'datetime13')
, (14, 'orange', 'datetime14')
    ;

SELECT fa.id, fa.fruit, fa.zdate
    , fo.id, fo.fruit, fo.zdate
FROM fruits fa
JOIN fruits fo ON fa.zdate < fo.zdate
WHERE fa.fruit = 'apple' AND fo.fruit = 'orange'
AND NOT EXISTS (
    SELECT *
    FROM fruits nx
    WHERE nx.fruit = 'orange'
    AND nx.zdate > fa.zdate
    AND nx.zdate < fo.zdate
    )   
AND NOT EXISTS (
    SELECT *
    FROM fruits nx
    WHERE nx.fruit = 'apple'
    AND nx.zdate < fo.zdate
    AND nx.zdate > fa.zdate
    )   
    ;

結果:

DROP TABLE
CREATE TABLE
INSERT 0 10
 id | fruit |   zdate    | id | fruit  |   zdate    
----+-------+------------+----+--------+------------
  1 | apple | datetime01 |  2 | orange | datetime02
  3 | apple | datetime03 |  4 | orange | datetime04
  5 | apple | datetime05 |  6 | orange | datetime06
 12 | apple | datetime12 | 13 | orange | datetime13
(4 rows)
于 2012-06-04T15:33:34.227 に答える