You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效编写SQL查询每个成员的最新可用状态记录?

问题说明

我有一张存储每个成员可用状态的表,仅包含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查询:

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倍,性能表现很差。我确定存在更优的解决方案但暂时无法实现。请问获取预期结果的正确方式是什么?


解决方案

使用窗口函数ROW_NUMBER()可以高效实现需求,仅需一次表扫描即可完成,无需多层嵌套子查询,性能远高于当前的嵌套IN查询写法。
优化后的查询语句如下:

WITH ranked_availabilities AS (
    SELECT 
        a.member_id,
        a.availablity_status_id,
        a.start_date,
        ROW_NUMBER() OVER (
            PARTITION BY a.member_id 
            ORDER BY a.start_date DESC, a.availablity_id DESC
        ) AS rn
    FROM availablities a
    WHERE a.start_date <= NOW()
)
SELECT 
    s.status_code,
    r.start_date,
    r.member_id
FROM ranked_availabilities r
JOIN availablity_status s 
    ON s.availablity_status_id = r.availablity_status_id
WHERE r.rn = 1;

方案优势

  • 仅扫描一次availablities表,嵌套子查询版本需要多次关联扫描表,数据量越大性能优势越明显
  • 逻辑清晰,PARTITION BY member_id按成员分组,ORDER BY start_date DESC取最新的生效时间,同时间的记录按自增主键倒序取最新插入的记录,避免同时间多条记录的冲突问题

性能优化建议

可以创建联合索引进一步提升查询效率,该索引可以直接覆盖窗口函数的分区、排序逻辑,查询可以直接走索引无需额外排序:

CREATE INDEX idx_availabilities_member_start ON availablities (member_id, start_date DESC, availablity_id DESC);

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 03:57:02