7

1分ごとにすべてのデータをカウントする次のクエリがあります。

$sql= "SELECT COUNT(*) AS count, date_trunc('minute', date) AS momento
FROM p WHERE fk_id_b=$id_b GROUP BY date_trunc('minute', date) 
ORDER BY momento ASC";

私がする必要があるのは、各行のカウントと過去2分間のカウントの合計を取得することです。

For example with the result of the $sql query above
|-------date---------|----count----|
|2012-06-21 05:20:00 |      12     |
|2012-06-21 05:21:00 |      14     |
|2012-06-21 05:22:00 |      10     |
|2012-06-21 05:23:00 |      20     |
|2012-06-21 05:24:00 |      25     |
|2012-06-21 05:25:00 |      30     |
|2012-06-21 05:26:00 |      10     |  

I want this result:

|-------date---------|----count----|
|2012-06-21 05:20:00 |      12     |   
|2012-06-21 05:21:00 |      26     |     12+14
|2012-06-21 05:22:00 |      36     |     12+14+10
|2012-06-21 05:23:00 |      44     |     14+10+20
|2012-06-21 05:24:00 |      55     |     10+20+25
|2012-06-21 05:25:00 |      75     |     20+25+30
|2012-06-21 05:26:00 |      65     |     25+30+10
4

3 に答える 3

12

現在の行と前の N 行 (この場合は N=2) の値の合計に対するより一般的な解決策を次に示します。

SELECT "date", 
sum("count") OVER (order by "date" ROWS BETWEEN 2 preceding AND current row)
FROM t
ORDER BY "date";

N は 0 から "Unbounded" の間で変更できます。このアプローチにより、アプリに「過去 N 分間のカウント」というパラメーターを設定する機会が得られます。また、範囲外の場合はデフォルト値を処理する必要はありません。

詳細については、PostgreSQL のドキュメント ( 4.2.8. Window Function Calls )を参照してください。

于 2012-10-30T14:20:21.273 に答える
12

lag()これは、ウィンドウ関数ではそれほどトリッキーではありません( SQL Fiddleでも):

CREATE TABLE t ("date" timestamptz, "count" int4);
INSERT INTO t VALUES
('2012-06-21 05:20:00',12),
('2012-06-21 05:21:00',14),
('2012-06-21 05:22:00',10),
('2012-06-21 05:23:00',20),
('2012-06-21 05:24:00',25),
('2012-06-21 05:25:00',30),
('2012-06-21 05:26:00',10);

SELECT *,
    "count"
    + coalesce(lag("count", 1) OVER (ORDER BY "date"), 0)
    + coalesce(lag("count", 2) OVER (ORDER BY "date"), 0) AS "total"
  FROM t;
  1. dateおよびcount列は予約語であるため、二重引用符で囲みました。
  2. lag(field, distance)現在の行から離れたfield列行の値を提供するため、最初の関数は前の行の値を提供し、2 番目の呼び出しは前の行の値を提供します。distance
  3. coalesce()NULLは関数からの結果を避けるために必要ですlag()(クエリの最初の行には「前の」行がないため、ですNULL) 。totalNULL
于 2012-06-29T20:28:31.203 に答える
9

@vyegorovの答えはほとんどそれをカバーしています。しかし、私はコメントに収まるよりも多くの不満を持っています。

  1. のような予約語datecount識別子として使用ないでください。PostgreSQLでは、すべてのSQL標準を除いて、これら2つの特定のキーワードを識別子として使用できます。しかし、それはまだ悪い習慣です。二重引用符で囲まれたものを識別子として使用できるという事実は"; DELETE FROM tbl;"、それを良い考えにさえしません。"date"その上、aの名前timestampは誤解を招く恐れがあります。

  2. 間違ったデータ型。例ではtimestamp、ではなくを表示しますtimestamptz。ここでは違いはありませんが、それでも誤解を招く可能性があります。

  3. 必要ありませんCOALESCE()ウィンドウ関数lag()lead()使用すると、3番目のパラメーターとしてデフォルト値を指定できます。

この設定に基づいて構築:

CREATE TABLE tbl (ts timestamp, ct int4);
INSERT INTO tbl VALUES
  ('2012-06-21 05:20:00', 12)
, ('2012-06-21 05:21:00', 14)
, ('2012-06-21 05:22:00', 10)
, ('2012-06-21 05:23:00', 20)
, ('2012-06-21 05:24:00', 25)
, ('2012-06-21 05:25:00', 30)
, ('2012-06-21 05:26:00', 10);

クエリ:

SELECT ts, ct + lag(ct, 1, 0) OVER (ORDER BY ts)
              + lag(ct, 2, 0) OVER (ORDER BY ts) AS total
FROM   tbl;

またはさらに良いことに:カスタムウィンドウフレームで単一sum()のウィンドウ集計関数を使用します:

SELECT ts, sum(ct) OVER (ORDER BY ts ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
FROM   tbl;

同じ結果。
関連している:

于 2012-06-29T21:14:01.323 に答える