-1

書き直す必要がある SQL クエリを作成しました。基本的に、それは次のようなことをします:

select log_number, 
    code_id, 
    code_name, 
    ... 
    buyer_id,
    ...
    rank() over (
        partition by code_id, buyer_id 
        order by (date_trunc('second',cdr.dateconso) - date_trunc('second',log.datecrea)) asc
        ) as ranking,
from ...
join ... on ...
left join ... on ...
join ...
where ...

また、PostgreSQL の最新バージョンで完全に動作します。

ただし、次の命令:

rank() over (
    partition by code.blg_promocode_keyid, cdr.tph_wp_account_buyer_keyid 
    order by (date_trunc('second',cdr.dateconso) - date_trunc('second',log.datecrea)) asc
    ) as ranking,

... 現在インストールされている PostgreSQL バージョンで構文エラーが発生し、それを回避する解決策を見つける必要がありますが、手がかりがありません。

エラー : クエリが失敗しました: エラー: "over" またはその付近で構文エラーが発生しました LINE 21: rank() over (partition by ...

4

1 に答える 1

1

それは些細なことかもしれません..

select log_number,
   ...
   rank() over (
        partition by code_id, buyer_id 
        order by (date_trunc('second',cdr.dateconso)
                - date_trunc('second',log.datecrea))
        ) as ranking,
from ...

..実際に最後の項目の後にコンマがある場合(これはすべきではありません)。SELECT

.. か否か

後のコメントで明らかにされているように、目的は、ウィンドウ関数のない古いバージョンの PostgreSQL (バージョン 8.2 以前) でエミュレートすることです。rank()

本当にすべきこと、ウィンドウ機能を備えたより新しいバージョン (PostgreSQL 8.4 以降) にアップグレードすることです。PostgreSQL 8.2 は 2011 年 12 月にサポートが終了しました。

それを除けば、 PostgreSQL 8.2の一時シーケンス一時テーブル、いくつかのサブクエリ、および集計関数rank()を使用してエミュレートできます。しかし、それはきれいではありません:

テストのセットアップ(あなたの例から簡略化)

CREATE TEMP TABLE t(code_id int, buyer_id int, the_date date);
INSERT INTO t  VALUES
 (1, 1, '2012-08-01')
,(1, 1, '2012-08-01')
,(1, 1, '2012-08-01')
,(1, 1, '2012-08-02')
,(1, 1, '2012-08-03')
,(1, 1, '2012-08-04')
,(2, 3, '2012-09-01')
,(2, 3, '2012-09-02')
,(2, 3, '2012-09-02')
,(2, 3, '2012-09-02')
,(2, 3, '2012-09-04')
,(2, 3, '2012-09-06');

一時テーブルを使用して、結果を複数回再利用します。現代の PostgreSQL では、代わりに CTE を使用します。一時的なシーケンスは
、. すべての列で基本的な行番号の順序を取得するには-その順序で:row_number()nextval()PARTITION BYORDER BYrank()

CREATE TEMP SEQUENCE t_seq;  -- once per session ..
-- SELECT setval('t_seq', 1, FALSE); --  .. or reset for repeated use

-- DROP TABLE tmp; 
CREATE TEMP TABLE tmp AS     -- once per session or drop first
SELECT code_id
      ,buyer_id
      ,the_date
      ,nextval('t_seq') AS rownum
       -- rank() included to compare results in modern version
       -- remove this line in old version:
      ,rank() OVER (PARTITION BY code_id, buyer_id ORDER BY the_date) AS rnk
FROM   t
ORDER  BY code_id, buyer_id, the_date;

Depesz がここで示しているような言語C関数を書くこともできます...

rownum次に、ピア グループごとの最小値を取得し( subquery peer)、グループごとの最小値を減算してrownum( subquery grp)、実際の行番号に到達します。

SELECT t.*, peer.rn - grp.rn AS rnk_8_2
FROM   tmp t
JOIN (
   SELECT code_id, buyer_id, min(rownum) -1 AS rn
   FROM   tmp
   GROUP  BY code_id, buyer_id
   ) grp USING (code_id, buyer_id)
JOIN (
   SELECT code_id, buyer_id, the_date, min(rownum) AS rn
   FROM   tmp
   GROUP  BY code_id, buyer_id, the_date
   ) peer USING (code_id, buyer_id, the_date)
ORDER BY code_id, buyer_id, the_date;

出来上がり。rnk_8_2一致しrnkます。

クリーンアップ (またはセッションの終了時にオブジェクトを削除):

DROP SEQUENCE t_seq;
DROP TABLE t, tmp; 

セッション/実行ごとに一時オブジェクトを作成/リセット/再作成する必要があることに注意してください。
PostgreSQL 9.1 でテスト済みですが、8.2 でも動作するはずです。

于 2012-09-21T10:34:32.950 に答える