首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何编写SQL以返回符合条件的行,如果条件不满足则返回另一行。

如何编写SQL以返回符合条件的行,如果条件不满足则返回另一行。
EN

Stack Overflow用户
提问于 2019-04-19 08:51:10
回答 3查看 68关注 0票数 1

我一直在编写SQL查询,这个函数类似于在一个月内返回学生的最新正式考试成绩,或者如果学生没有正式考试成绩,则返回最新的模拟考试成绩。

例如,这里有一张用来保存考试成绩的表格,列“mode”用于正式考试或模拟考试。

代码语言:javascript
运行
复制
name          class        mode      score   exam_time
Alice         Math         mock      92      2019-03-21 10:00:00
Alice         Math         formal    88      2019-03-18 10:00:00
Alice         Math         formal    95      2019-03-07 10:00:00
Alice         Science      mock      89      2019-03-13 14:00:00
Bob           Math         mock      96      2019-03-21 10:00:00
Bob           Math         formal    90      2019-03-18 10:00:00
Bob           Math         formal    95      2019-03-07 10:00:00
Bob           Science      mock      98      2019-03-13 14:00:00

需要有如下查询结果:

代码语言:javascript
运行
复制
Alice    Math    formal    88     2019-03-18 10:00:00
Alice    Science mock      89     2019-03-13 14:00:00
Bob      Math    formal    90     2019-03-18 10:00:00
Bob      Science mock      98     2019-03-13 14:00:00

对于数学,有正式考试和模拟考试,所以需要返回最新的正式考试,对于科学,只有模拟考试,所以返回模拟考试。

由于其他考虑,需要在一个SQL语句中实现它。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-04-19 12:25:16

这与Kaushik的方法略有不同。distinct on是要走的路,但我会将逻辑写成:

代码语言:javascript
运行
复制
select distinct on (name, class) t.*
from t 
order by name, class, (mode = 'formal') desc, exam_time desc;

distinct on为分组中的每组值返回一行(括号中的内容)。该行是由order by确定的第一行。

票数 2
EN

Stack Overflow用户

发布于 2019-04-19 09:11:50

在Postgres,我更喜欢DISTINCT ON来获得每个组的最高记录。它的性能稍好一些。

代码语言:javascript
运行
复制
select DISTINCT ON (name,class) t.*
   from  t ORDER BY name,class,
    case when mode = 'formal' 
  then 0 else 1 end,exam_time desc ;

DEMO

票数 1
EN

Stack Overflow用户

发布于 2019-04-19 08:56:43

我们可以在这里使用row_number

代码语言:javascript
运行
复制
select name, class, mode, score, exam_time
from
(
    select t.*, row_number() over (partition by name, class
                                   order by case when mode = 'formal' then 0 else 1 end,
                                            date_trunc('month', exam_time) desc) rn
    from your_table t
) t
where rn = 1;

上面与row_number一起使用的分区逻辑将所有正式记录放在所有模拟记录之前。这意味着,只有在根本没有此类最新正式记录的情况下,才会返回模拟记录。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55759133

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档