【问题标题】:SQL get latest availability per memberSQL 获取每个成员的最新可用性
【发布时间】:2021-11-12 16:00:28
【问题描述】:

我有一种情况,我将每个成员的可用性存储在一个表中。 这是一个有 4 列的简单表格。

CREATE TABLE availablities (
  availablity_id serial PRIMARY KEY,
  member_id serial,
  availablity_status_id serial,
  start_date timestamp
);

每个成员可以在表中有多个记录并获取当前状态 我为每个成员获取最近 start_date 小于 now() 的记录。

我首先尝试了一个幼稚的 Max() 和 Group by query

select 
  status_code, max(start_date) start_date,availablities.member_id 
from 
  availablities
join 
  availablity_status on availablity_status.availablity_status_id = availablities.availablity_status_id
where 
  start_date <= now() 
group by 
  status_code,availablities.member_id;

但这会为每个用户返回多条记录,因为我按用户和状态获取最新记录。

我终于想出了一个可以给我预期结果的查询。

 select status_code,start_date,a2.member_id  from availablities a2 
 join availablity_status on availablity_status.availablity_status_id = a2.availablity_status_id
 where a2.availablity_id in(
     select 
        max(availablity_id)
     from availablities a 
     where 
        a.member_id = a2.member_id and 
        start_date in(
            select 
                max(start_date) start_date
            from availablities
            where 
            start_date <= now() 
            and a.member_id = availablities.member_id    
     )
);

但是这个查询需要 60 倍的时间来执行并且感觉不对。 我很确定一定有更好的解决方案,但我无法动手。

获得预期结果的正确方法是什么?

我创建了一个 DB-fiddle 以使其更易于查看。查询 1 不正确,当我们有更多数据时,查询 2 会慢得多。

https://www.db-fiddle.com/f/iWgvuj8kcms9F5CKuoKsny/2

【问题讨论】:

    标签: sql postgresql performance


    【解决方案1】:

    看来你需要在这里使用一个简单的row_number 窗口函数:

    with a as (
        select *, Row_Number() over(partition by member_id order by start_date desc, availablity_id desc) rn
        from availablities 
        where start_date<now()
    )
    select s.status_code, a.start_date, a.member_id
    from a join availablity_status s on s.availablity_status_id=a.availablity_status_id
    where rn=1
    

    请注意,您的数据选择性不够,所以对于 member_id 3,它是否可用?如果有两个相同的日期,最近的日期是多少?

    我添加了一个 tie-breaker 以也按 availability_id 排序以获得您的预期结果

    其实是availablity_id - 你这里好像有一个常见的错字!

    查看您的updated Fiddle

    【讨论】:

    • 谢谢,Row_Number 和 partition by 正是我想要的。它比我最初错误的请求还要快。
    猜你喜欢
    • 2016-01-01
    • 2016-05-15
    • 2013-11-22
    • 1970-01-01
    • 2020-12-22
    • 2021-01-10
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多