根据两个字段获取最新记录
Get latest record based on two fields
我有一个包含以下字段的 table:
user_id year month amount type
--------------------------------------------------
5 2018 1 100 Foo
6 2017 12 100 Bar
6 2018 11 100 Foo
6 2018 12 100 Bar
7 2018 12 100 Foo
7 2019 12 100 Bar
8 2019 12 100 Foo
我想做 3 件事:
- 获取某些用户的每个用户id的最新记录(1条记录,最新年份和月份字段),
类似于:
select *
from myTable
where user_id in (6,7) and <is latest year / month>
哪个应该return
user_id year month amount type
---------------------------------------------------
6 2018 12 100 Bar
7 2019 12 100 Foo
- 计算上述查询的总数,类似于:
select SUM(amount) as myTotal, avg(amount) as myAverage,
(count # of foos in result) as numberOfFoos,
(count # of bars in result) as numberOfBars
from myTable
where user_id in (6,7) and <is latest year / month>
这将 return 包含自定义字段的一行:
myTotal myAverage numberOfFoos numberOfBars
--------------------------------------------------------
300 100 2 1
- 与上述查询相同,但针对一段时间内的每个月,例如。在过去的 3-5 年中,最好是尽可能少的调用,而不是手动循环 36 个月以上并进行单独调用。
year month myTotal myAverage numberOfFoos numberOfBars
--------------------------------------------------------------------------
2018 1 300 100 2 1
2018 2 300 100 2 1
2018 3 300 100 2 1
...
2020 12 300 100 2 1
第一个问题可以使用 row_number
函数解决:
with d as (
select
users.*,
row_number() over (partition by user_id order by year desc, month desc ) rn
from users
where user_id in (5, 6)
)
select * from d
where rn = 1;
第二个问题可以用同样的方法解决:
with d as (
select
users.*,
row_number() over (partition by user_id order by year desc, month desc) rn
from users
where user_id in (6, 7)
)
select
sum(amount), avg(amount),
count(*) filter (where type = 'Foo') count_foo,
count(*) filter (where type = 'Bar') count_bar
from d
where rn = 1;
select year, month, sum(amount), avg(amount),
sum(case when type = 'Foo' then 1 else 0 end) as num_foos,
sum(case when type = 'Bar' then 1 else 0 end) as num_bars
from (select u.*,
row_number() over (partition by user_id order by year desc, month desc ) as seqnum
from users
where user_id in (5, 6)
) u
where seqnum = 1
group by year, month;
我有一个包含以下字段的 table:
user_id year month amount type
--------------------------------------------------
5 2018 1 100 Foo
6 2017 12 100 Bar
6 2018 11 100 Foo
6 2018 12 100 Bar
7 2018 12 100 Foo
7 2019 12 100 Bar
8 2019 12 100 Foo
我想做 3 件事:
- 获取某些用户的每个用户id的最新记录(1条记录,最新年份和月份字段),
类似于:
select *
from myTable
where user_id in (6,7) and <is latest year / month>
哪个应该return
user_id year month amount type
---------------------------------------------------
6 2018 12 100 Bar
7 2019 12 100 Foo
- 计算上述查询的总数,类似于:
select SUM(amount) as myTotal, avg(amount) as myAverage,
(count # of foos in result) as numberOfFoos,
(count # of bars in result) as numberOfBars
from myTable
where user_id in (6,7) and <is latest year / month>
这将 return 包含自定义字段的一行:
myTotal myAverage numberOfFoos numberOfBars
--------------------------------------------------------
300 100 2 1
- 与上述查询相同,但针对一段时间内的每个月,例如。在过去的 3-5 年中,最好是尽可能少的调用,而不是手动循环 36 个月以上并进行单独调用。
year month myTotal myAverage numberOfFoos numberOfBars
--------------------------------------------------------------------------
2018 1 300 100 2 1
2018 2 300 100 2 1
2018 3 300 100 2 1
...
2020 12 300 100 2 1
第一个问题可以使用 row_number
函数解决:
with d as (
select
users.*,
row_number() over (partition by user_id order by year desc, month desc ) rn
from users
where user_id in (5, 6)
)
select * from d
where rn = 1;
第二个问题可以用同样的方法解决:
with d as (
select
users.*,
row_number() over (partition by user_id order by year desc, month desc) rn
from users
where user_id in (6, 7)
)
select
sum(amount), avg(amount),
count(*) filter (where type = 'Foo') count_foo,
count(*) filter (where type = 'Bar') count_bar
from d
where rn = 1;
select year, month, sum(amount), avg(amount),
sum(case when type = 'Foo' then 1 else 0 end) as num_foos,
sum(case when type = 'Bar' then 1 else 0 end) as num_bars
from (select u.*,
row_number() over (partition by user_id order by year desc, month desc ) as seqnum
from users
where user_id in (5, 6)
) u
where seqnum = 1
group by year, month;