2

免責事項: 私は PostgreSQL が初めてで、plpgSQL の関数も初めてです。ドキュメントを読みましたが、困惑しています。

とにかく、アスタリスク CDR 評価の表から電荷バンドを選択するために、この機能があります。

CREATE FUNCTION getBand(
    callDateTime varchar
) RETURNS varchar AS $$
/* Select correct charging band */
DECLARE
    callTime varchar;
    callDay varchar;
    theBand varchar;
BEGIN
    /* Find the time and the day of the call */
    callTime := to_char(to_timestamp(callDateTime,'YYYY-MM-DD HH24:MI:SS'),'HH24:MI:SS');
    callDay := to_char(to_timestamp(callDateTime,'YYYY-MM-DD HH24:MI:SS'),'Day');
    theBand := band 
    FROM bands 
    WHERE day = callDay 
    AND start < callTime 
    AND finish > callTime 
    LIMIT 1;
    RETURN theBand;
END;
$$ LANGUAGE plpgsql

入力文字列は、アスタリスク CDR テーブルから取得され、'YYYY-MM-DD HH24:MI:SS' の形式になっています。

バンド テーブルの形式は次のとおりです。

day | band | start | finish
============================

「day」は平日の名前、band は通話の料金帯 (「ピーク」、「オフピーク」、「週末」) であり、start と finish はその料金帯の開始時刻と終了時刻です。

私が走るとき

SELECT getBand('2013-05-03 11:30:00');

NULL の結果が得られます。

私が走るとき

SELECT band FROM bands
WHERE day = 'Friday' AND start < '11:30:00' and finish > '11:30:00' LIMIT 1;

(私のデータに対して) 正しい答えが得られました:「ピーク」

よくわかりません。どこが間違っているのか教えてほしい人はいますか?

4

3 に答える 3

1
CREATE FUNCTION get_band(call_ts timestamp)
  RETURNS text AS
$func$
   SELECT band 
   FROM   bands 
   WHERE  day = to_char(call_ts,'FMDay')
   AND    start <= call_ts::time
   AND    finish > call_ts::time
   ORDER  BY start 
   LIMIT  1
$func$ LANGUAGE sql STABLE;
  • テンプレートパターン 'Day'はあなたにto_char()与えます、私は引用します:

    完全大文字の曜日名 (9 文字まで空白埋め)

    空白のパディングを削除するには、テンプレート パターン修飾子:がありFMます。だからそれを作ってください:'FMDay'。の必要はありませんtrim()

  • YYYY-MM-DD HH24:MI:SSは標準の ISO 8601 形式で、どのロケールでも機能します。を使用する正当な理由はありません。最初varcharから atimestampにしてください。はい、ある時点のデータ型は Postgres ではタイムスタンプと呼ばれます ( ではありませんdatetime)。そのため、パラメーター名を選択しcall_tsました。

  • 引用符で囲まれていない、大文字と小文字が混在する識別子は使用しないでください。これまで。混乱を招くだけです。それらはすべて小文字にキャストされます。それが私が選んだ次の理由ですcall_ts

  • から ato_char()を取得するために使用しないでください。キャストするだけです。はるかに簡単で高速です。timetimestampcall_ts::time

  • この単純なクエリにはplpgsqlはまったく必要ありません。単純なSQL関数にするか、単にクエリを使用してください。

  • plpgsql では、多くの小さな割り当て(比較的コストがかかる)の代わりに、SQL コマンドを機能させるのが最善です。に変換していなくてもLANGUAGE sql、この 1 つのコンパクトなクエリを使用します。

  • LIMIT 1withoutORDER BYは、いつでも変更できる任意の結果を提供します。どの行を取得するかを気にする場合、または少なくとも安定させたい場合は、追加する必要がありますORDER BY!

  • と時間間隔を空けるのは疑わしい慣習 start < x AND finish > xです。通常は下限を含めたいので、 を使用し<=ました。

  • タイムゾーンを考慮しましたか?

  • 曜日の代わりに整数を保存します。

于 2013-05-04T15:03:04.913 に答える