这可能是微不足道的..
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.2rank()
中借助临时序列、临时表、一些子查询和聚合函数进行模拟。但这并不漂亮:
测试设置(从您的示例中简化)
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 在这里演示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;
瞧。rnk_8_2
匹配rnk
。
清理(或让对象在会话结束时被丢弃):
DROP SEQUENCE t_seq;
DROP TABLE t, tmp;
请注意,您必须为每个会话/执行创建/重置/重新创建临时对象。
在 PostgreSQL 9.1 中测试,但应该在 8.2 中工作。