3

特定のコンピューターの今日の平均接続数を 7 ~ 14 日前の平均接続数と比較するクエリを作成しようとしています。これはウィンドウ関数で処理するのが最適だと考えましたが、日付の正しい構文を取得できません。

iptable という名前の IP アドレスと接続レコードのテーブルがあり、列として soucreip、destinationip、timestamp があるとします。sourceip ごとのカウントを取得するために、前の 7 日間のウィンドウに対して試みているクエリを次に示します。

select 
  sourceip, 
  destinationip, 
  timestamp, 
  count(*) OVER (PARTITION BY sourceip order by timestamp
                 RANGE BETWEEN now() - '7 day'::Interval PRECEDING
                               now() - '14 day'::Interval FOLLOWING)
from
 iptable;

このタイプのクエリを作成する最良の方法は何ですか? ウィンドウ関数アプローチは理にかなっていますか? または、大きなテーブルの場合により最適化された方法はありますか?

4

2 に答える 2

7

問題の一部は、ひどい列名を選択したことです"timestamp"。組み込みデータ型の名前であるため、列名として使用するには、どこでもtimestamp使用する必要があります。"double quote"

それだけではありません。ウィンドウ関数の構文が間違っています。ウィンドウ関数の構文を参照してください。AND;を忘れました ですRANGE BETWEEN .. PRECEDING AND ... FOLLOWING

また、問題の原因ではありませんが、current_timestamp代わりにSQL 標準を使用する必要がありますnow()

これにより、新しいエラーが発生します。

CREATE TABLE iptable ( sourceip cidr, destinationip cidr, "timestamp" timestamptz);

regress=> select 
  sourceip, 
  destinationip, 
  timestamp, 
  count(*) OVER (PARTITION BY sourceip order by "timestamp" RANGE BETWEEN current_timestamp - '7 day'::Interval PRECEDING AND current_timestamp - '14 day'::Interval FOLLOWING)

from
 iptable;
ERROR:  RANGE PRECEDING is only supported with UNBOUNDED
LINE 5: ... OVER (PARTITION BY sourceip order by "timestamp" RANGE BETW...
                                                             ^

これは、現在のウィンドウ関数の実装が、やりたいことを実行しないことを示唆しています。悲しいことに。

値 PRECEDING および値 FOLLOWING のケースは、現在、ROWS モードでのみ許可されています。それらは、フレームが現在の行の前後の行で開始または終了することを示します。value は、変数、集約関数、またはウィンドウ関数を含まない整数式でなければなりません。

代わりに、入力行にフィルターを付けたプレーンGROUP BYを使用するだけです。WHERE

select 
  sourceip,
  count(sourceip) AS n_conns_7_to_14_days_ago
from
 iptable
WHERE age("timestamp") BETWEEN INTERVAL '7' DAY AND INTERVAL '14' DAY
GROUP BY sourceip;
于 2012-11-14T00:37:02.010 に答える
5

取得するため ...

7 ~ 14 日前の平均接続数

SELECT sourceip, destinationip, timestamp, count(*) AS ct
FROM   iptable
WHERE  "timestamp" BETWEEN now() - '14 day'::interval
                   AND     now() -  '7 day'::interval
GROUP BY 1,2,3;

単純な集計関数を使用してください。また、列名として
使用しないでください。timestampSQL 標準では保護された単語であり、PostgreSQL では部分的に予約されています。

于 2012-11-14T00:43:14.327 に答える