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,Students 和 Presences。
presents 是一个 3 列 table : student_id, day, present.
我希望查询突出显示过去 2 天缺勤的所有学生。
这将 return 一个包含 3 列的 table:Student_Id,姓名,如果错过了最后两天,我怎样才能得到这个结果?
table 结构是
学生 id: int, name: varchar
Presence student_id: int, day: date, present: boolean
一个数据示例
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。你的查询有点惨,如果你能描述清楚,我会尽力帮助你解决问题
我有一个不定期的艺术课程。 每天我都会在 table.
中添加一个新的 "present" 条目我想知道最近两天错过的学生是什么。就在最后 2 天。
Important, each student choose a different weekday to have a class. and some of them 2 days per week.
我有 2 个 tables,Students 和 Presences。
presents 是一个 3 列 table : student_id, day, present.
我希望查询突出显示过去 2 天缺勤的所有学生。
这将 return 一个包含 3 列的 table:Student_Id,姓名,如果错过了最后两天,我怎样才能得到这个结果?
table 结构是
学生 id: int, name: varchar
Presence student_id: int, day: date, present: boolean
一个数据示例
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。你的查询有点惨,如果你能描述清楚,我会尽力帮助你解决问题