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

SQL同一SELECT查询中如何实现两个筛选条件交替生效

交替匹配SQL查询实现方案

实现逻辑

逐行状态切换的匹配逻辑无法通过普通集合级WHERE条件实现,因为普通查询无法在遍历过程中保存上一行的匹配状态,整体实现分两个核心步骤:

  • 先为表数据按遍历要求生成连续递增行号:注意SQL标准中不存在可靠的"默认存储顺序",必须显式指定排序规则(可根据业务使用自增主键、入库时间、业务编码排序,保证遍历顺序符合预期)
  • 逐行扫描数据并维护匹配状态:从第一行开始,初始匹配目标为@Random1,当前行命中则将下一行的匹配目标切换为另一个参数,未命中则保持当前匹配目标不变,直到遍历完所有行,最终返回所有命中的记录。

支持CTE的数据库写法(SQL Server/MySQL 8.0+/PostgreSQL)

-- 入参定义
DECLARE @Random1 INT = 56;
DECLARE @Random2 INT = 91;

WITH OrderedData AS (
    SELECT
        *,
        -- 按业务要求的遍历顺序生成连续行号,ORDER BY可根据实际规则调整
        ROW_NUMBER() OVER (ORDER BY Date_input, Code) AS rn
    FROM CODE_DEX
),
RecursiveMatch AS (
    -- 递归起点:处理第一行数据,初始匹配目标为@Random1
    SELECT
        rn,
        Code,
        FirstNo,
        LastNo,
        Date_input,
        CASE WHEN FirstNo = @Random1 THEN 1 ELSE 0 END AS is_match,
        CASE WHEN FirstNo = @Random1 THEN @Random2 ELSE @Random1 END AS next_target
    FROM OrderedData
    WHERE rn = 1

    UNION ALL

    -- 递归处理后续行
    SELECT
        curr.rn,
        curr.Code,
        curr.FirstNo,
        curr.LastNo,
        curr.Date_input,
        CASE WHEN curr.FirstNo = prev.next_target THEN 1 ELSE 0 END AS is_match,
        CASE
            WHEN curr.FirstNo = prev.next_target THEN
                -- 命中则切换下一行的匹配目标
                CASE WHEN prev.next_target = @Random1 THEN @Random2 ELSE @Random1 END
            ELSE
                -- 未命中则保持原有匹配目标
                prev.next_target
        END AS next_target
    FROM OrderedData curr
    JOIN RecursiveMatch prev ON curr.rn = prev.rn + 1
)
-- 返回所有命中记录
SELECT Code, FirstNo, LastNo, Date_input
FROM RecursiveMatch
WHERE is_match = 1
-- SQL Server需要加下一行取消递归深度限制,其他数据库可删除
OPTION (MAXRECURSION 0);

以上代码用提供的样例数据、入参@Random1=56、@Random2=91运行,返回结果完全符合预期:

CodeFirstNoLastNoDate_input
ABCD567856782022/07/07
ABCD911191112022/07/07

低版本MySQL(5.x)兼容写法

不支持CTE的版本可以用用户变量实现逐行状态维护:

-- 入参定义
SET @Random1 = 56;
SET @Random2 = 91;
-- 初始化状态变量
SET @curr_target = @Random1;

SELECT Code, FirstNo, LastNo, Date_input
FROM (
    SELECT
        *,
        @is_match := CASE WHEN FirstNo = @curr_target THEN 1 ELSE 0 END AS is_match,
        @curr_target := CASE
            WHEN @is_match = 1 THEN
                CASE WHEN @curr_target = @Random1 THEN @Random2 ELSE @Random1 END
            ELSE @curr_target
        END AS dummy
    FROM CODE_DEX
    -- 必须指定排序规则,保证遍历顺序正确
    ORDER BY Date_input, Code
) t
WHERE is_match = 1;

注意事项

  • 所有写法中ORDER BY子句必须和要求的遍历顺序完全一致,无ORDER BY的查询返回顺序会随索引变更、数据增删发生变化,不存在稳定的"默认存储顺序"。
  • 如果业务上有明确的自增主键ID,直接用ID作为排序字段即可,是最可靠的遍历顺序依据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:42:14