我编写了一个需要重写的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版本生成语法错误,我必须找到绕过它的解决方案,但我不知道。
错误:查询失败:错误:语法错误处于或接近“超过”第21行: rank()over(partition by ...
答案 0 :(得分: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 中模拟rank()
- 版本8.2或更早版本。
应该做的是升级到具有窗口功能的更新版本(PostgreSQL 8.4或更高版本)。 PostgreSQL 8.2 has reached end-of-life in Dec.2011
除此之外,您可以借助临时序列,临时表,某些子查询来模拟rank()
PostgreSQL 8.2中的聚合函数。但它并不漂亮:
测试设置(从您的示例中简化)
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 BY
和ORDER BY
rank()
所有列的基本行号顺序,请按顺序获取:
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 demonstrates here等语言C
函数...
现在,获得每个对等组的最小rownum
(子查询peer
)并减去每个组的最小rownum
(子查询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;
VOILÀ。 rnk_8_2
匹配rnk
。
清理(或在会话结束时丢弃对象):
DROP SEQUENCE t_seq;
DROP TABLE t, tmp;
请注意,您必须为每个会话/执行创建/重置/重新创建临时对象 在PostgreSQL 9.1中测试过,但应该在8.2中工作。