1

問題

データベースのカーネルを使用するプロジェクトに取り組んでいますが、私の PostgreSQL のスキルは壁にぶつかっています。クロス積を計算するために 2 つのテーブルを結合しています。つまり、

SELECT (d1.a * d2.a + d1.b * d2.b) AS dot FROM data d1, data d2

これにより、すべてのベクトル間のクロス積が得られます。テーブルに次のデータがある

 a | b | c 
---+---+---
 1 | 1 | 1
 2 | 2 | 2
 3 | 3 | 3

上記のコマンドは

 dot 
-----
   2
   4
   6
 ...

たとえば、行 2 とその前の行と次の行の間の内積を計算したい場合、どうすれば効率的に計算できますか?

試み

ウィンドウ関数を使用しようとしましたが、集計関数のみを計算するため、失敗しました。行を隣接する行 (つまり、そのウィンドウ) と結合したいのですが、これらの集計は計算しません。これらの行に沿ったもの:

SELECT a * a + b * b + c * c
    OVER(rows between 1 preceding and 1 following) as value FROM data data;

私もrow_number() OVER()どの作品を使用しようとしました。しかし、ネストされたサブクエリでは、これは不器用で非効率的です。

SELECT d1.a * d3.a + d1.b * d3.b + d1.c * d3.c 
    FROM data d1, 
    (SELECT * FROM 
        (SELECT *, row_number() OVER() as index from data) d2 
    WHERE d2.index >= 1 AND d2.index <=3) d3;

LATERAL最後に、私はsを掘り下げようとしましたが、うまくいきませんでした。

何かご意見は?

4

1 に答える 1

2

lag()/で前後の行の値を取得できますlead()
行の順序が によって決定されるa場合、クエリは次のようになります。

SELECT
  a,
  (lag(a, 1, 0) OVER (ORDER BY a)) * (lead(a, 1, 0) OVER (ORDER BY a))
  + (lag(b, 1, 0) OVER (ORDER BY a)) * (lead(b, 1, 0) OVER (ORDER BY a))
  + (lag(c, 1, 0) OVER (ORDER BY a)) * (lead(c, 1, 0) OVER (ORDER BY a)) AS dot_preceding_and_following
FROM ( VALUES
  (1, 1, 1),
  (2, 2, 2),
  (3, 3, 3)
) T(a, b, c)
ORDER BY
  a
;
于 2016-05-08T08:20:51.653 に答える