我一直在写SQL查询,该函数类似于在一个月内返回学生的最新正式考试成绩,或者如果没有针对学生的正式考试,则返回最新的模拟考试成绩。
例如,这是保存考试成绩的表,“模式”列用于正式考试或模拟考试。
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
查询结果必须为:
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
对于Math,既有形式考试又有模拟考试,因此需要返回最新的形式考试;对于Science,只有模拟考试,因此应返回模拟考试。
出于其他考虑,需要在一条SQL语句中实现它。
答案 0 :(得分:2)
这是Kaushik的方法的微小变化。 class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::enableForeignKeyConstraints();
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
是必经之路,但我将逻辑写为:
ngAfterViewInit(): void {
if(this.el.nativeElement.value==null||this.el.nativeElement.value==""){
this.el.nativeElement.setAttribute("custom-attribute", "false");
}else{
this.el.nativeElement.setAttribute("custom-attribute", "true")
}
}
distinct on
为分组中的每组值(括号中的内容)返回一行。该行是由select distinct on (name, class) t.*
from t
order by name, class, (mode = 'formal') desc, exam_time desc;
确定的第一行。
答案 1 :(得分:1)
在Postgres中,我更喜欢DISTINCT ON
获得每个组的最高记录。性能稍好。
select DISTINCT ON (name,class) t.*
from t ORDER BY name,class,
case when mode = 'formal'
then 0 else 1 end,exam_time desc ;
答案 2 :(得分:0)
我们可以在此处使用row_number
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
一起使用的分区逻辑将所有正式记录放在所有模拟记录之前。这意味着仅在根本没有此类最新正式记录的情况下,才会返回模拟记录。