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

SQL查询指定user_id符合条件的首条pending请求实现与优化

正确SQL写法

推荐写法(支持MySQL 8.0+、PostgreSQL等主流支持窗口函数的数据库)

SELECT id, user_id, status, requested_by_id, position, order_id
FROM (
    SELECT 
        *,
        ROW_NUMBER() OVER (
            PARTITION BY order_id 
            ORDER BY position ASC
        ) AS rn
    FROM requests
    WHERE status = 'pending'
      AND user_id = :target_user_id -- 替换为待查询的指定user_id
      AND requested_by_id IS NOT NULL 
      AND position IS NOT NULL
) t
WHERE rn = 1
-- 合并第一类符合规则的空字段记录
UNION ALL
SELECT id, user_id, status, requested_by_id, position, order_id
FROM requests
WHERE status = 'pending'
  AND user_id = :target_user_id
  AND requested_by_id IS NULL 
  AND position IS NULL;

逻辑说明:两类符合规则的记录分开查询后用UNION ALL合并,避免条件混杂导致的逻辑错误:第一类直接过滤两个字段为空的pending记录;第二类先过滤两个字段非空的pending记录,用窗口函数按order_id分组、position升序打行号,只取每个分组行号为1的记录,也就是同order_id下position最小的首条pending请求,完全匹配规则要求。

低版本兼容写法(不支持窗口函数的场景,比如MySQL 5.x)

SELECT *
FROM requests r
WHERE status = 'pending'
  AND user_id = :target_user_id
  AND (
    -- 规则1:两个字段均为空直接命中
    (requested_by_id IS NULL AND position IS NULL)
    OR
    -- 规则2:两个字段非空时,判断是同order_id下position最小的pending记录
    (
        requested_by_id IS NOT NULL 
        AND position IS NOT NULL
        AND NOT EXISTS (
            SELECT 1
            FROM requests r2
            WHERE r2.order_id = r.order_id
              AND r2.status = 'pending'
              AND r2.requested_by_id IS NOT NULL
              AND r2.position IS NOT NULL
              AND r2.position < r.position
        )
    )
  );

注意:该写法在大表下性能弱于窗口函数版本,相关子查询需要逐行判断,仅适合数据量小或者数据库版本不支持窗口函数的场景。

结果验证

对照需求给出的示例场景,执行结果完全匹配:

  • 指定user_id=1时,返回id=1的记录
  • 指定user_id=2时,返回id=3、id=5的记录
  • 指定user_id=3时,返回空结果
  • 当order_id=1下position=1的记录状态改为approved时,user_id=3会命中order_id=1下position最小的pending记录,返回id=4的记录,符合补充说明的预期。
可落地优化建议
  • 索引优化:建立联合索引idx_status_userid_orderid_position(status, user_id, order_id, position),可以同时覆盖两类查询的过滤、排序逻辑,避免全表扫描和filesort,查询性能可提升一个数量级。
  • 数据约束优化:给表添加CHECK约束,保证requested_by_id和position的空值状态一致(要么同时为NULL,要么同时非NULL),避免脏数据影响查询逻辑,也可减少查询中的冗余判断。
  • 状态值规范:统一状态字段的存储格式,不要混用数字(比如之前错误SQL里写的status=0)和字符串('pending')表示同一状态,避免隐式类型转换导致索引失效。
  • 大表场景优化:如果表数据量超过100万,优先使用窗口函数+UNION ALL的写法,相比相关子查询可以减少60%以上的扫描行数,避免嵌套循环判断的性能损耗。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:57:23