我需要使用PostgreSQL来转移带有fk的最后2条记录的表:
目前我有一个具有这种结构的表:
id | fk | start_date | end_date | value
---------------------|------------|-------
01 | 01 | 2017-10-01 | 2017-11-01 | 1
02 | 01 | 2017-12-10 | 2018-01-10 | 9
03 | 01 | 2018-01-10 | 2018-02-10 | 2
04 | 02 | 2017-11-10 | 2017-12-10 | 1
05 | 02 | 2017-12-10 | 2018-01-10 | 2
06 | 03 | 2017-12-10 | 2018-01-10 | 8
我想用这种结构输出:
fk | start_date_1 | end_date_1 | value_1 | start_date_2 | end_date_2 | value_2
---|--------------|------------|---------|--------------|------------|---------
01 | 2018-01-10 | 2018-02-10 | 2 | 2017-12-10 | 2018-01-10 | 9
02 | 2017-12-10 | 2018-01-10 | 2 | 2017-11-10 | 2017-12-10 | 1
03 | 2017-12-10 | 2018-01-10 | 8 | NULL | NULL | NULL
我需要一个可用于搜索最后2条记录和最后24条记录的代码。
答案 0 :(得分:0)
您可以在分析/窗口功能的帮助下完成此操作。
具有最后2个记录案例的临时表的工作解决方案:
创建测试数据:
drop table testdata;
create table testdata(id integer, fk integer, start_date date, end_date date, value integer);
insert into testdata values(1, 1, '2017-10-01', '2017-11-01', 1);
insert into testdata values(2, 1, '2017-12-10', '2018-01-10', 9);
insert into testdata values(3, 1, '2018-01-10', '2018-02-10', 2);
insert into testdata values(4, 2, '2017-11-10', '2017-12-10', 1);
insert into testdata values(5, 2, '2017-12-10', '2018-01-10', 2);
insert into testdata values(6, 3, '2017-12-10', '2018-01-10', 8);
创建一个帮助表,按日期排序,然后从中选择数据透视表:
WITH ranked AS (
SELECT id, fk, start_date, end_date,value, RANK() OVER (PARTITION BY fk ORDER BY start_date desc) from testdata
)
select fk,
(select start_date as start_date_1 from ranked where rank=1 and ranked.fk=testdata.fk),
(select end_date as end_date_1 from ranked where rank=1 and ranked.fk=testdata.fk),
(select value as value_1 from ranked where rank=1 and ranked.fk=testdata.fk),
(select start_date as start_date_2 from ranked where rank=2 and ranked.fk=testdata.fk),
(select end_date as end_date_2 from ranked where rank=2 and ranked.fk=testdata.fk),
(select value as value_2 from ranked where rank=2 and ranked.fk=testdata.fk)
from testdata group by fk order by fk;
结果:
fk start_date_1 end_date_1 value_1 start_date_2 end_date_2 value_2
---------------------------------------------------------------------------------------------------
1 2018-01-10 2018-02-10 2 2017-12-10 2018-01-10 9
2 2017-12-10 2018-01-10 2 2017-11-10 2017-12-10 1
3 2017-12-10 2018-01-10 8 <null> <null> <null>
恕我直言,你的方法对于最后24个案例来说是不切实际的。你真的想要处理一个24 * 3 + 1列的表吗?
如果我是你,我会为最后24条记录创建一个排名表/结果,并在应用程序方面进行处理。查询最后24个:
select * from (
select id, fk, start_date, end_date, value, rank() OVER (PARTITION BY fk ORDER BY start_date desc) from testdata
) as r where rank < 25;
答案 1 :(得分:0)
如果我对您的理解正确,也可以使用LATERAL join来实现;
对于t1的fk中的每个值,LATERAL join搜索t2中的第二个值。
select t1.fk,
t1.start_date as start_date_1,
t1.end_date as end_date_1,
t1._value as _value1,
_second.*
from
(
--get first record of last two
select distinct on (dt.fk) dt.fk,dt.start_date,dt.end_date,dt._value
from (
--last 24 records
select * from table1 order by start_date DESC limit 24
) dt
order by dt.fk,dt.start_date DESC
) t1
LEFT JOIN LATERAL(
--get second record of last two
select start_date as start_date_2,
end_date as end_date_2,
_value as _value2
from table1 as t2
where t2.fk = t1.fk and
t1.start_date > t2.start_date --to get second value
order by t2.start_date desc
limit 1) _second on true;