SQL 如何根据条件计算每个 ID 的最后条目

SQL how count last entries for each id based on a criteria

我有一个不定期的艺术课程。 每天我都会在 table.

中添加一个新的 "present" 条目

我想知道最近两天错过的学生是什么。就在最后 2 天。

Important, each student choose a different weekday to have a class. and some of them 2 days per week.

我有 2 个 tables,StudentsPresences

presents 是一个 3 列 table : student_id, day, present.

我希望查询突出显示过去 2 天缺勤的所有学生。

这将 return 一个包含 3 列的 table:Student_Id,姓名,如果错过了最后两天,我怎样才能得到这个结果?

table 结构是

一个数据示例

presences                                   students
student_id  day           present           id   name  
---------------------------------           ------------
1           2016-01-01    0                 1    'Bob'
1           2016-01-10    1                 2    'Carol'
1           2016-01-20    0

2           2016-01-15    1
2           2016-01-27    0
2           2016-01-21    0

在这种情况下,Bob 只错过了最后一天,而 Carol 错过了最后 2 天。预期结果将是:

student_id  name   misses_two_last_days 
----------------------------------------
1           Bob     FALSE
2           Carol   TRUE

您必须为您在查询中使用的表定义别名。

例如:

SELECT s.id, s.name, p.day FROM 
Students s, Presences p 
WHERE s.id = p.student_id

您的查询有很多问题。尝试重写它以使用 joins。您还必须定义最近 2 天。我试图用下面的 subquery 来做到这一点。然后你需要使用 aggregation 来查看学生是否错过了这两天。这是应该接近的东西:

select s.id, s.name
from students s
   inner join presences p on s.id = p.student_id and p.present = false
   inner join (select distinct day 
               from presences 
               order by day desc 
               limit 2) t on p.day = t.day
group by s.id, s.name
having count(p.day) = 2

重读你的问题,如果你想 return 所有学生,而不仅仅是那些错过了最后 2 天的学生,你需要使用 outer joins 并删除 having子句并替换为 case 语句:

select s.id, s.name, 
    case when count(p.day) = 2 then 'missed' else '' end as Missed
from students s
   left join presences p on s.id = p.student_id and p.present = false
   left join (select distinct day 
               from presences 
               order by day desc 
               limit 2) t on p.day = t.day
group by s.id, s.name

另一种解决方案只有一个子层。请检查是否符合您的要求。

SELECT 
    s.id, 
    s.name,
    ( SELECT SUM(p.present = false)
      FROM p
      WHERE p.student_id = s.id 
      ORDER BY p.day DESC
      LIMIT 2 ) AS misses_two_last_days
FROM s;

既然你只提供了很少的信息,我可以告诉你的是你的子查询有什么问题:

SELECT COUNT(*) FROM 
(SELECT p.student_id 
       FROM p WHERE p.student_id = s.id  ORDER BY p.day DESC LIMIT 2) AS subquery
WHERE p.present = false

让我们检查一下,您将 table 重命名为 子查询,但您的 where 仍在使用 p.present 这就是你得到错误的原因。数据库无法获取什么是 p。你的查询有点惨,如果你能描述清楚,我会尽力帮助你解决问题