4

以下に示すような構造のデータベーステーブルがあります。

CREATE TABLE dated_records (
              recdate DATE NOT NULL
              col1    DOUBLE NOT NULL,
              col2    DOUBLE NOT NULL,
              col3    DOUBLE NOT NULL,
              col4    DOUBLE NOT NULL,
              col5    DOUBLE NOT NULL,
              col6    DOUBLE NOT NULL,
              col7    DOUBLE NOT NULL,
              col8    DOUBLE NOT NULL
              );

指定された列(col1、col2、col3など)について、指定された2つの日付間の変更を含むレコードを返すことができるSQLステートメントを記述したいと思います。

たとえば、col1、col2、およびcol3の値が2つの日付の間にどの程度変化したかを確認したい場合です。これを行うためのばかげた方法は、各日付の行を(別々に)選択してから、データベースサーバーの外部のフィールドを区別することです-

SQL1 = "SELECT col1, col2 col3 FROM dated_records WHERE recdate='2001-01-01'";
SQL1 = "SELECT col1, col2 col3 FROM dated_records WHERE recdate='2001-02-01'";

ただし、純粋なSQLを使用して差分を実行するよりスマートな方法があると確信しています。自己結合(および場合によってはネストされたサブクエリ)の使用が含まれると推測していますが、複雑すぎる可能性があります-ここでSQLの専門家に、この問題をどのように解決するかを尋ねたほうがよいと判断しました。最も効率的な方法。

理想的には、SQLはDBに依存しない必要がありますが、特定のデータベースに関連付ける必要がある場合は、PostgreSQLである必要があります。

4

5 に答える 5

4

2つの行を選択し、それらを1つに結合して、値を減算するだけです。

select d1.recdate, d2.recdate,
       (d2.col1 - d1.col1) as delta_col1,
       (d2.col2 - d1.col2) as delta_col2,
       ...
from (select *
      from dated_records
      where recdate = <date1>
     ) d1 cross join
     (select *
      from dated_records
      where recdate = <date2>
     ) d2
于 2012-05-07T21:36:11.253 に答える
2

2つのselectクエリと交差しない結果セットの行を取得する場合は、EXCEPT演算子を使用できると思います。

EXCEPT演算子は、最初の結果セットにはあるが2番目の結果セットにはない行を返します。

したがって、2つのクエリは、それらを結合する例外演算子を使用して1つのクエリになります。

SELECT col1, col2 col3 FROM dated_records WHERE recdate='2001-01-01'
EXCEPT
SELECT col1, col2 col3 FROM dated_records WHERE recdate='2001-02-01'
于 2012-05-07T21:37:17.197 に答える
0

ウィンドウ関数に加えてDISTINCT:を使用できます。

SELECT DISTINCT
       first_value(recdate) OVER () AS date1
      ,last_value(recdate)  OVER () AS date2
      ,last_value(col1)     OVER () - first_value(col1) OVER () AS delta1
      ,last_value(col2)     OVER () - first_value(col2) OVER () AS delta2
       ...
FROM   dated_records
WHERE  recdate IN ('2001-01-01', '2001-01-03')

任意の2日間。単一のインデックスまたはテーブルスキャンを使用するため、高速である必要があります。

ウィンドウを注文しませんでしたが、すべての計算で同じウィンドウが使用されるため、値は一貫しています。

このソリューションは、n行間の計算に簡単に一般化できます。この場合、ウィンドウ関数のPostgresアーセナルnth_value()から使用することをお勧めします。

于 2012-05-08T00:52:43.673 に答える
0

単純なデルタを探している場合、これはこれを書くためのより速い方法のように思われました。

SELECT first(col1) - last(col1) AS delta_col1
, first(col2) - last(col2) AS delta_col2
FROM dated_records WHERE recdate IN ('2001-02-01', '2001-01-01')

最初の行と2番目の行のどちらが最初に来るかわからない場合がありますが、いつでも答えをラップすることができますabs(first(col1)-last(col1))

于 2012-05-08T03:47:13.203 に答える
0
SELECT
COALESCE
(a.col1 -
  (
    SELECT b.col1
    FROM dated_records b
    WHERE b.id = a.id + 1
  ),
a.col1)
FROM dated_records a
WHERE recdate='2001-01-01';
于 2012-05-07T21:52:06.887 に答える