选择具有不同字段的最后一行
Posted
技术标签:
【中文标题】选择具有不同字段的最后一行【英文标题】:Select Last Rows with Distinct Field 【发布时间】:2021-01-25 12:24:44 【问题描述】:我有一个具有以下架构的表:
id itemid date some additional data
1 1000 10/12/2020 a
2 1000 10/12/2020 b
3 1002 09/12/2020 c
4 1001 07/12/2020 d
5 1000 05/12/2020 e
6 1005 03/12/2020 f
7 1003 03/12/2020 g
在此表中,只有 id
字段是唯一的。我关心的是获取包含最后一个 X 不同 itemid
的行,按日期排序。
例如,在上面的示例中,如果我想获得最后 3 个不同的 itemid
,我将获得前 4 行,因为在前 4 行中我们有三个不同的 itemid
: 1000、1002 和 1001。我不确定如何使用单个 SQL 语句来实现。
【问题讨论】:
我不明白这个。如果您想获得不同的 itemid,那么您为什么期望前 4 行会重复 itemid = 1000 表中有不同的第 1 行和第 2 行的附加字段 - 我关心的是获取与最后 X 个不同 itemid 相关的所有数据 - 让我更新架构。 请注意,表格有列,而不是字段。 是的,我的错.... 【参考方案1】:如果我理解正确,您想计算每行(按日期)的不同项目 ID 的数量,并返回计数为 3 的所有行。
如果 Postgres 支持这个,你可以使用:
select t.*
from (select t.*,
count(*) filter (where id = min_id) over (order by date desc) as cnt_itemid
from (select t.*,
min(id) over (partition by itemid order by date desc) as min_id
from t
) t
) t
where cnt_itemid <= 3;
唉,Postgres 不支持 COUNT(DISTINCT)
作为窗口函数。但是你可以使用DENSE_RANK()
来计算它:
select t.*
from (select t.*,
count(*) over (filter where id = min_id) as cnt_itemid
from (select t.*,
min(id) over (partition by itemid order by date) as min_id
from t
) t
) t
where cnt_itemid <= 3;
但是,这会返回所有在第 4 项之前的最新行——因此它有额外的行。
要获得四行,您需要项目 id 为“3”的第一行。一种方法是:
select t.*
from (select t.*, min(id) filter (where cnt_itemid = 3) over () as min_cnt_itemid_3
from (select t.*,
count(*) filter (where id = min_id) over (order by date desc) as cnt_itemid
from (select t.*,
min(id) over (partition by itemid order by date desc) as min_id
from t
) t
) t
) t
where id <= min_cnt_itemid_3;
您也可以通过识别“第三项”的第一次出现然后选择该行之前的所有行来做到这一点:
select t.*
from t join
(select itemid, min(max_date) over () as min_max_date
from (select t.itemid, max(date) as max_date
from t
group by t.itemid
order by max(t.date) desc
limit 3
) t
) tt
on t.itemid = tt.itemid and t.date >= tt.min_max_date;
This fiddle 显示其中的每一个。
【讨论】:
三个只是我用来说明示例的数字 - 我想要实现的是获取有关最后 X 个不同 itemid 的所有数据 - 让我举例说明 - 假设 itemid 是文章并且此表中的行代表文章上的 cmets,我想获取最近 X 篇文章上的所有 cmets(行)。例如 - 最近 20 篇文章中的所有 cmets。 因此查询将是“按日期降序排列表格,继续选择行,直到计算出 X 个不同的 itemid”【参考方案2】:您可以按如下方式使用解析函数:
select * from
(select t.*,
conut(distinct item_id) over (order by date desc) as cnt
from your_Table t) t
where cnt <= 3
【讨论】:
以上是关于选择具有不同字段的最后一行的主要内容,如果未能解决你的问题,请参考以下文章
使用具有不同 order by 子句的 postgres 窗口函数
在一个查询Access数据库中从具有不同字段的两个不同表中选择列