我要从下表中找到按fname和lname分组的新代码和上一个代码。
fname | lname | code |
----------------------
jack | jonas | 987 |
nick | fun | 563 |
jack | jonas | 674 |
jack | jonas | 672 |
输出表:
fname | lname | new_code | prev_code |
-------------------------------------
jack | jonas | 987 | 674
PS:我的情况不支持“ 与众不同”。我猜可以使用左连接或数据透视。
答案 0 :(得分:1)
使用row_number()
widown功能,如下尝试
with cte as
(
select *,
row_number() over(partition by fname,lname order by date desc) rn
from table_name
), cte1 as
(
select * from cte where rn<=2
), select fname,lname,
max(case when rn=1 then code end) as code,
max(case when rn=2 then code end) as prevcode fron cte1
group by fname,lnamae
答案 1 :(得分:1)
SELECT
*
FROM (
SELECT DISTINCT ON (fname, lname)
*,
lead(code) OVER (PARTITION BY fname, lname ORDER BY my_date DESC) as prev
FROM
my_table
ORDER BY
fname, lname, my_date DESC
) s
WHERE prev IS NOT NULL
lead()
window function提供了先前的代码DISTINCT ON
过滤每个组的第一个数据集WHERE
子句对其进行过滤答案 2 :(得分:1)
您可以使用窗口函数first_value,nth_value例如
select
distinct on (fname, lname)
first_value(fname ) over (PARTITION by fname, lname order by some_date desc RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING),
first_value(lname ) over (PARTITION by fname, lname order by some_date desc RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING),
nth_value(code,1) over (PARTITION by fname, lname order by some_date desc RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING),
nth_value(code,2) over (PARTITION by fname, lname order by some_date desc RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
from public.tbl_test
答案 3 :(得分:1)
在Postgres中,您可以使用distinct on
和lag()
获得每个名称的最新对:
select distinct on (lname, fname) t.*
from (select t.*,
lag(code) over (partition by lname, fname order by datecol) as prev_code
from t
) t
where prev_code is not null
order by lname, fname, date desc;
您也可以在不使用子查询的情况下执行此操作:
select distinct lname, fname,
first_value(code) over (partition by lname, fname order by datecol desc),
nth_value(code, 2) over (partition by lname, fname order by datecol desc)
from t;
但是,当第二个代码在那里时,您仍然需要一个子查询来过滤值。
或者,您可以使用数组:
select lname, fname,
(array_agg(code order by datecol desc))[1] as code,
(array_agg(code order by datecol desc))[2] as prev_code
from t
group by lname, fname
having count(*) >= 2;