1

開始と終了のタイムスタンプに基づいて、データの範囲に対していくつかの基本的な統計を行う関数があります。

CREATE OR REPLACE FUNCTION cal(TIMESTAMP, TIMESTAMP, OUT Date_Time timestamp with time zone, OUT avg numeric, OUT stddev numeric, OUT Rstedv_per numeric) 
AS $$
SELECT
    max(datetime) as Date_Time,
    avg(SO2) AS Mean,
    stddev_samp(so2) as STD_DEV,
    stddev_samp(so2)/avg(SO2)*100 as Rstedv_Per
FROM Table43
WHERE datetime > $1 AND datetime < $2;
$$
 LANGUAGE SQL;

これは、次のような単純な単一選択でうまく機能します。

select * FROM
 cal('2014-08-02 05:29:00', '2014-08-02 05:32:00')

しかし今、別の関数を作成するのに問題があり、「cal」関数の複数の呼び出しを組み合わせることができる select ステートメントさえも作成できません。たとえば、3 つの期間を含むテーブルを返したいとします。したがって、戻り値は 4 列 x 3 行になります。

「2014-08-02 05:29:00」、「2014-08-02 05:32:00」
「2014-08-02 05:35:00」、「2014-08-02 05:39:00」
「2014-08-02 05:45:00」、「2014-08-02 05:49:00」
4

2 に答える 2

0

式を使用しVALUESて、複数行の入力日付を提供します。それで ...

Postgres のすべてのバージョン

SELECT cal(a, b)
FROM  (
   VALUES 
      ('2014-08-02 05:29'::timestamp, '2014-08-02 05:32'::timestamp)
    , ('2014-08-02 05:35', '2014-08-02 05:39')
    , ('2014-08-02 05:45', '2014-08-02 05:39')
   ) v(a, b);

VALUES式を実際のテーブルに置き換えることができます。

これにより、行全体が (個々の列ではなく) 1 つの列として返されます。でその場で分解でき(cal(a, b)).*ます。これは機能しますが、非効率的です。Postgres パーサーの弱点により、これにより関数が複数回評価されることになります。詳細な説明:

代わりに、パフォーマンスを向上させるためにサブクエリを使用してください。

SELECT (rec).*
FROM  (
    SELECT cal(a, b)
    FROM  (
       VALUES 
          ('2014-08-02 05:29'::timestamp, '2014-08-02 05:32'::timestamp)
        , ('2014-08-02 05:35', '2014-08-02 05:39')
        , ('2014-08-02 05:45', '2014-08-02 05:39')
       ) v(a, b)
   ) sub;

SQL Fiddle (pg 8.3 が古いバージョンで動作することを示すため)。

SELECT リスト内のセットを返す関数は一部の人に嫌われており、非標準の SQL であるためです。

Postgres 9.3+

これが、Postgres 9.3 が導入された主な理由です (SQL 標準準拠) LATERAL JOIN

SELECT f.*
FROM  (
   VALUES 
      ('2014-08-02 05:29'::timestamp, '2014-08-02 05:32'::timestamp)
    , ('2014-08-02 05:35', '2014-08-02 05:39')
    , ('2014-08-02 05:45', '2014-08-02 05:39')
   ) v(a,b)
  , cal(v.a, v.b) f;

FROM リストの 2 番目の項目が前のテーブルを明示的に参照するため、ここではLATERAL JOIN暗黙的です。詳細:

現在の Postgres 9.3 のSQL Fiddle 。

于 2014-08-13T17:10:00.183 に答える
0

日付がパラメーターの場合、次のようなものが必要になります。

select * 
FROM cal('2014-08-02 05:29:00', '2014-08-02 05:32:00')
union all
select * 
FROM cal('2014-08-02 05:35:00', '2014-08-02 05:39:00')
union all
select * 
FROM cal('2014-08-02 05:45:00', '2014-08-02 05:39:00')

PostgreSQL 9.0+

select cal(a, b)
from 
    values( 
    ('2014-08-02 05:29:00', '2014-08-02 05:32:00'),
    ('2014-08-02 05:29:00', '2014-08-02 05:32:00'),
    ('2014-08-02 05:29:00', '2014-08-02 05:32:00')
    ) as dates (a, b)

日付がテーブルから取得され、 Postresql 9.3を使用している場合:

select cal.*
FROM 
  (select '2014-08-02 05:29:00' a, '2014-08-02 05:32:00' b
      from foo_table) as dates
left join lateral cal(dates.a, dates.b) cal on true
于 2014-08-13T16:23:59.657 に答える