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

如何在SQL存储过程中过滤自定义字段cour与year?

问题描述

我编写了如下SQL代码,通过CASE语句生成了自定义字段cour和year,需要在存储过程中根据这两个字段进行数据筛选。

原查询代码:

SELECT 
    s.kid, ep.exper_id, ep.exper_name, mp.md_name, 
    mo.md_option_id, kk.external_id,
    mv.completed_id,
    COUNT(ce.times_observed) AS countoftimes,
    CASE
        WHEN kid = '7180' THEN '044986'
        WHEN kid = '7800' THEN '044984' 
    END AS cour,
    CASE 
        WHEN CE.yid = '2024' THEN '2023-24'
        WHEN CE.yid = '2023' THEN '2022-23'  
    END AS [year]
FROM
    ks.reqe_md_pool mp, ks.reqe_md_options mo, 
    ks.reqe_md_values mv, ks.reqe_experiences_pool ep,
    ks.reqe_completed_experiences ce
LEFT JOIN
    ks.oasis_person kk ON kk.person_id = ce.student_id
LEFT JOIN  
    ks.oasis_schedule s ON ce.schedule_id = s.schedule_id, 
    ks.reqe_list_version lv 
WHERE 
    ep.exper_id = '1492'
    AND mv.md_id = mp.md_id 
    AND ce.exper_id = ep.exper_id 
    AND ce.completed_id = mv.completed_id 
    AND mv.md_option_id = mo.md_option_id 
    AND ce.list_version_id = lv.list_version_id 
GROUP BY 
    s.kid, s.did, s.cid, s.lid, ep.exper_id, ep.exper_name,
    mp.md_id, mp.md_name, mo.md_option_id, mo.md_option_order, 
    mo.md_option_name, ce.student_id, mv.text_answer, mv.md_value_id,
    mv.completed_id, CE.YID, kk.external_id         

我尝试将原查询作为子查询后添加WHERE条件,但写法存在问题:

SELECT * 
FROM
    (*code at the top* ) 
WHERE
    cour = @cour
    AND year = @year

也尝试过使用CROSS APPLY,但cour字段因关联的表使用了LEFT JOIN而未生效:

SELECT 
    s.kid, ep.exper_id, ep.exper_name, mp.md_name, 
    mo.md_option_id, kk.external_id,
    mv.completed_id,
    C.UCFCOURSEID AS cour
FROM
    ks.reqe_md_pool mp, ks.reqe_md_options mo, 
    ks.reqe_md_values mv, ks.reqe_experiences_pool ep,
    ks.reqe_completed_experiences ce
LEFT JOIN
    ks.oasis_person kk ON kk.person_id = ce.student_id
LEFT JOIN  
    ks.oasis_schedule s ON ce.schedule_id = s.schedule_id, 
    ks.reqe_list_version lv 
CROSS APPLY (SELECT 
    CASE WHEN kid='7180' THEN '044986'
         WHEN kid='7800' THEN '044984'
    END AS UCFCOURSEID) C
WHERE 
    ep.exper_id = '1492'
    AND mv.md_id = mp.md_id 
    AND ce.exper_id = ep.exper_id 
    AND ce.completed_id = mv.completed_id 
    AND mv.md_option_id = mo.md_option_id 
    AND ce.list_version_id = lv.list_version_id 
GROUP BY 
    s.kid, s.did, s.cid, s.lid, ep.exper_id, ep.exper_name,
    mp.md_id, mp.md_name, mo.md_option_id, mo.md_option_order, 
    mo.md_option_name, ce.student_id, mv.text_answer, mv.md_value_id,
    mv.completed_id, CE.YID, kk.external_id, C.UCFCOURSEID        

请问如何在SQL存储过程中实现对cour和year字段的筛选?


解决方案

方法1:使用CTE封装原查询后筛选

CTE比子查询更易读,可直接引用自定义字段。注意year是SQL关键字,需用方括号包裹:

CREATE PROCEDURE YourProcedureName
    @cour VARCHAR(20),
    @year VARCHAR(10)
AS
BEGIN
    WITH CTE_Results AS (
        SELECT 
            s.kid, ep.exper_id, ep.exper_name, mp.md_name, 
            mo.md_option_id, kk.external_id,
            mv.completed_id,
            COUNT(ce.times_observed) AS countoftimes,
            CASE
                WHEN s.kid = '7180' THEN '044986'
                WHEN s.kid = '7800' THEN '044984' 
            END AS cour,
            CASE 
                WHEN CE.yid = '2024' THEN '2023-24'
                WHEN CE.yid = '2023' THEN '2022-23'  
            END AS [year]
        FROM
            ks.reqe_md_pool mp
            JOIN ks.reqe_md_options mo ON mv.md_option_id = mo.md_option_id
            JOIN ks.reqe_md_values mv ON mv.md_id = mp.md_id
            JOIN ks.reqe_experiences_pool ep ON ce.exper_id = ep.exper_id
            JOIN ks.reqe_completed_experiences ce ON ce.completed_id = mv.completed_id
            JOIN ks.reqe_list_version lv ON ce.list_version_id = lv.list_version_id
            LEFT JOIN ks.oasis_person kk ON kk.person_id = ce.student_id
            LEFT JOIN ks.oasis_schedule s ON ce.schedule_id = s.schedule_id
        WHERE 
            ep.exper_id = '1492'
        GROUP BY 
            s.kid, s.did, s.cid, s.lid, ep.exper_id, ep.exper_name,
            mp.md_id, mp.md_name, mo.md_option_id, mo.md_option_order, 
            mo.md_option_name, ce.student_id, mv.text_answer, mv.md_value_id,
            mv.completed_id, CE.YID, kk.external_id         
    )
    SELECT *
    FROM CTE_Results
    WHERE cour = @cour
      AND [year] = @year;
END

方法2:直接将CASE条件移至WHERE子句(性能更优)

无需封装子查询,直接用原始字段逻辑替代自定义字段,减少查询层级:

CREATE PROCEDURE YourProcedureName
    @cour VARCHAR(20),
    @year VARCHAR(10)
AS
BEGIN
    SELECT 
        s.kid, ep.exper_id, ep.exper_name, mp.md_name, 
        mo.md_option_id, kk.external_id,
        mv.completed_id,
        COUNT(ce.times_observed) AS countoftimes,
        CASE
            WHEN s.kid = '7180' THEN '044986'
            WHEN s.kid = '7800' THEN '044984' 
        END AS cour,
        CASE 
            WHEN CE.yid = '2024' THEN '2023-24'
            WHEN CE.yid = '2023' THEN '2022-23'  
        END AS [year]
    FROM
        ks.reqe_md_pool mp
        JOIN ks.reqe_md_options mo ON mv.md_option_id = mo.md_option_id
        JOIN ks.reqe_md_values mv ON mv.md_id = mp.md_id
        JOIN ks.reqe_experiences_pool ep ON ce.exper_id = ep.exper_id
        JOIN ks.reqe_completed_experiences ce ON ce.completed_id = mv.completed_id
        JOIN ks.reqe_list_version lv ON ce.list_version_id = lv.list_version_id
        LEFT JOIN ks.oasis_person kk ON kk.person_id = ce.student_id
        LEFT JOIN ks.oasis_schedule s ON ce.schedule_id = s.schedule_id
    WHERE 
        ep.exper_id = '1492'
        -- 转换cour参数为原始kid条件
        AND (
            (@cour = '044986' AND s.kid = '7180')
            OR (@cour = '044984' AND s.kid = '7800')
        )
        -- 转换year参数为原始yid条件
        AND (
            (@year = '2023-24' AND CE.yid = '2024')
            OR (@year = '2022-23' AND CE.yid = '2023')
        )
    GROUP BY 
        s.kid, s.did, s.cid, s.lid, ep.exper_id, ep.exper_name,
        mp.md_id, mp.md_name, mo.md_option_id, mo.md_option_order, 
        mo.md_option_name, ce.student_id, mv.text_answer, mv.md_value_id,
        mv.completed_id, CE.YID, kk.external_id         
END

方法3:修正CROSS APPLY写法

用OUTER APPLY替代CROSS APPLY处理LEFT JOIN导致的NULL情况,同时将计算字段加入GROUP BY和WHERE:

CREATE PROCEDURE YourProcedureName
    @cour VARCHAR(20),
    @year VARCHAR(10)
AS
BEGIN
    SELECT 
        s.kid, ep.exper_id, ep.exper_name, mp.md_name, 
        mo.md_option_id, kk.external_id,
        mv.completed_id,
        COUNT(ce.times_observed) AS countoftimes,
        C.UCFCOURSEID AS cour,
        CASE 
            WHEN CE.yid = '2024' THEN '2023-24'
            WHEN CE.yid = '2023' THEN '2022-23'  
        END AS [year]
    FROM
        ks.reqe_md_pool mp
        JOIN ks.reqe_md_options mo ON mv.md_option_id = mo.md_option_id
        JOIN ks.reqe_md_values mv ON mv.md_id = mp.md_id
        JOIN ks.reqe_experiences_pool ep ON ce.exper_id = ep.exper_id
        JOIN ks.reqe_completed_experiences ce ON ce.completed_id = mv.completed_id
        JOIN ks.reqe_list_version lv ON ce.list_version_id = lv.list_version_id
        LEFT JOIN ks.oasis_person kk ON kk.person_id = ce.student_id
        LEFT JOIN ks.oasis_schedule s ON ce.schedule_id = s.schedule_id
        -- OUTER APPLY处理s.kid为NULL的场景
        OUTER APPLY (SELECT 
            CASE WHEN s.kid='7180' THEN '044986'
                 WHEN s.kid='7800' THEN '044984'
            END AS UCFCOURSEID) C
    WHERE 
        ep.exper_id = '1492'
        AND C.UCFCOURSEID = @cour
        AND (
            (@year = '2023-24' AND CE.yid = '2024')
            OR (@year = '2022-23' AND CE.yid = '2023')
        )
    GROUP BY 
        s.kid, s.did, s.cid, s.lid, ep.exper_id, ep.exper_name,
        mp.md_id, mp.md_name, mo.md_option_id, mo.md_option_order, 
        mo.md_option_name, ce.student_id, mv.text_answer, mv.md_value_id,
        mv.completed_id, CE.YID, kk.external_id, C.UCFCOURSEID        
END

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:02:21