SQL查询实现需求:根据问题的有效回答存在性筛选问答记录
SQL查询实现需求:根据问题的有效回答存在性筛选问答记录
老哥,我完全get到你的需求了——你就是想针对不同问题的回答情况智能筛选记录:要是某个问题有过非null的有效回答,那就只保留该问题的有效回答记录,把它的null记录过滤掉;要是某个问题从头到尾全是null回答,那就把这个问题的null记录保留下来。
我给你两种实现思路,都是能完美满足你需求的:
方法一:用临时集合(CTE)拆分逻辑
这种写法逻辑清晰,新手也容易理解:
WITH questions_with_valid_answers AS ( -- 先找出所有至少有一个有效回答的问题 SELECT DISTINCT question FROM your_table WHERE answer IS NOT NULL ) SELECT * FROM your_table t WHERE -- 场景1:当前记录是有效回答,且所属问题有过有效回答 (answer IS NOT NULL AND question IN (SELECT question FROM questions_with_valid_answers)) OR -- 场景2:当前记录是null回答,且所属问题从未有过有效回答 (answer IS NULL AND question NOT IN (SELECT question FROM questions_with_valid_answers));
逻辑解释:
- 先通过
questions_with_valid_answers这个临时集合,把所有存在有效回答的问题捞出来,DISTINCT是为了避免同一个问题重复出现。 - 主查询的两个条件分支正好对应你的需求:
- 对有过有效回答的问题(比如你例子里的「What did you eat today」),只保留它的非null回答(前两条记录),过滤掉该问题的null记录(第三条);
- 对没有过任何有效回答的问题(比如你例子里的「What did you eat yesterday」),保留它的null记录。
方法二:用窗口函数(更高效的写法)
如果你的数据库支持窗口函数(比如MySQL 8+、PostgreSQL、SQL Server等),这种写法性能更好,不需要重复查询临时集合:
SELECT question, answer FROM ( SELECT *, -- 按问题分组,统计每个问题的有效回答数量(COUNT自动忽略null) COUNT(answer) OVER (PARTITION BY question) AS valid_answer_count FROM your_table ) sub_query WHERE -- 有有效回答的问题,只留非null记录 (answer IS NOT NULL AND valid_answer_count > 0) OR -- 无有效回答的问题,留null记录 (answer IS NULL AND valid_answer_count = 0);
逻辑解释:
COUNT(answer) OVER (PARTITION BY question)会给每条记录加上一个标记,代表该记录所属问题的有效回答总数。因为COUNT函数在计算时会自动忽略null值,所以:
- 如果
valid_answer_count > 0,说明这个问题有过有效回答,我们只留它的非null记录; - 如果
valid_answer_count = 0,说明这个问题全是null回答,我们就留它的null记录。
你可以根据自己的数据库版本和实际数据量,选择适合的写法~
内容来源于stack exchange
相关产品推荐
相关产品推荐

