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

SQL查询:按Ques_ID拆分Ans_Tex到不同列并筛选指定数据

解决SQL行转列+多条件筛选问题(适合初学者)

嘿,作为SQL初学者遇到这种“同一ID重复出现,还要同时满足不同行条件”的问题太正常啦!我来一步步帮你搞定,不仅能把不同ques_id的ans_text放到不同列,还能精准筛选出符合要求的记录~

问题核心分析

你之前的查询里,同一个ID会因为ques_id=3和ques_id=17分成两行显示,而且直接在WHERE里加fs.QUES_ID=3 AND fs.ANS_TEXT='Non-MFG' AND fs.QUES_ID=17 AND fs.ANS_TEXT='Yes'肯定不行——因为同一行只能有一个ques_id,永远匹配不到同时满足两个条件的行!

咱们需要先把同一ID的两个答案合并到同一行的不同列,再筛选出同时符合两个条件的ID,或者先筛选符合条件的ID,再合并答案。

方法一:用INNER JOIN筛选+直接列展示(最简单易懂)

这种方法通过两次关联ADD_ANSW表,分别获取满足两个条件的记录,自动过滤掉不满足其中任何一个条件的ID,还能直接把两个答案放到不同列:

SELECT 
    p.ID,
    ISNULL(dbo.fnRemovePatternFromString(p.Last_Name, '%[,-.'']%'), '') AS [Last],
    ISNULL(dbo.fnRemovePatternFromString(p.First_Name, '%[,-.'']%'), '') AS [First],
    ISNULL(dbo.fnRemovePatternFromString(p.Middle_Initial, '%[,-.'']%'), '') AS [Middle],
    fs3.ANS_TEXT AS [Q3_Answer], -- ques_id=3的答案列
    fs17.ANS_TEXT AS [Q17_Answer] -- ques_id=17的答案列
FROM person p
INNER JOIN person_facilities pf ON p.ID = pf.ID
-- 只关联满足ques_id=3且ans_text='Non-MFG'的记录
INNER JOIN dbo.ADD_ANSW fs3 
    ON p.id = fs3.id 
    AND fs3.QUES_ID = 3 
    AND fs3.ANS_TEXT = 'Non-MFG'
-- 只关联满足ques_id=17且ans_text='Yes'的记录
INNER JOIN dbo.ADD_ANSW fs17 
    ON p.id = fs17.id 
    AND fs17.QUES_ID = 17 
    AND fs17.ANS_TEXT = 'Yes'
WHERE pf.Current_status = 'Employed'

为什么这个方法有效?

  • INNER JOIN会只保留同时匹配两个关联条件的ID,也就是必须同时存在ques_id=3且ans='Non-MFG'和ques_id=17且ans='Yes'的记录。
  • 直接把两个关联表的ANS_TEXT分别命名成不同列,不需要额外处理行转列的逻辑,对初学者特别友好。

方法二:用CASE WHEN行转列+EXISTS筛选(更灵活)

如果之后需要扩展更多ques_id的列,这种方法更灵活,先把所有答案转到同一行的不同列,再用EXISTS确保ID满足两个条件:

SELECT 
    p.ID,
    ISNULL(dbo.fnRemovePatternFromString(p.Last_Name, '%[,-.'']%'), '') AS [Last],
    ISNULL(dbo.fnRemovePatternFromString(p.First_Name, '%[,-.'']%'), '') AS [First],
    ISNULL(dbo.fnRemovePatternFromString(p.Middle_Initial, '%[,-.'']%'), '') AS [Middle],
    -- 用CASE WHEN把ques_id=3的答案提取到单独列
    MAX(CASE WHEN fs.QUES_ID = 3 THEN fs.ANS_TEXT END) AS [Q3_Answer],
    -- 用CASE WHEN把ques_id=17的答案提取到单独列
    MAX(CASE WHEN fs.QUES_ID = 17 THEN fs.ANS_TEXT END) AS [Q17_Answer]
FROM person p
INNER JOIN person_facilities pf ON p.ID = pf.ID
LEFT JOIN dbo.ADD_ANSW fs 
    ON p.id = fs.id 
    AND (fs.QUES_ID = 17 OR fs.QUES_ID = 3)
WHERE pf.Current_status = 'Employed'
-- 检查当前ID是否存在ques_id=3且ans='Non-MFG'的记录
AND EXISTS (
    SELECT 1 FROM dbo.ADD_ANSW fs3 
    WHERE fs3.id = p.id AND fs3.QUES_ID = 3 AND fs3.ANS_TEXT = 'Non-MFG'
)
-- 检查当前ID是否存在ques_id=17且ans='Yes'的记录
AND EXISTS (
    SELECT 1 FROM dbo.ADD_ANSW fs17 
    WHERE fs17.id = p.id AND fs17.QUES_ID = 17 AND fs17.ANS_TEXT = 'Yes'
)
GROUP BY p.ID, [Last], [First], [Middle]

关键部分解释

  • CASE WHEN:针对每个ques_id,只提取对应行的ANS_TEXT,其他行返回NULL,再用MAX()把同一ID的两个答案合并到同一行(因为MAX()会忽略NULL)。
  • EXISTS:用来检查同一个ID是否存在满足条件的行,不会像之前的WHERE那样限制同一行必须同时满足两个条件。

初学者小提示

  1. 当需要同一个实体(比如这里的person.ID)满足不同行的多个条件时,不要在WHERE里直接写矛盾的行条件(比如同时要求ques_id=3和ques_id=17),要用INNER JOIN多次、EXISTS或者GROUP BY + HAVING来实现。
  2. 行转列的需求,CASE WHEN比PIVOT更直观,适合新手理解和扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:48:36