问题
I'm building a system that should show when the students missed two days in a row. For example, this table contains the absences.
day | id | missed
----------------------------------
2016-10-6 | 1 | true
2016-10-6 | 2 | true
2016-10-6 | 3 | false
2016-10-7 | 1 | true
2016-10-7 | 2 | false
2016-10-7 | 3 | true
2016-10-10 | 1 | false
2016-10-10 | 2 | true
2016-10-10 | 3 | true
(days 2016-10-8 and 2016-10-9 are weekend)
in the case above:
- student 1 missed the days 1st and 2nd. (consecutive)
- student 2 missed the days 1st and 3rd. (nonconsecutive)
- student 3 missed the days 2nd and 3rd. (consecutive)
The query should select only student 1 and 3.
Is possible to do stuff like this just with a single SQL Query?
回答1:
Use inner join to connect two instances of the table- one with the 'first' day, and one with the 'second' day, and then just look for rows where both are missed:
select a.id from yourTable as a inner join yourTable as b
on a.id = b.id and a.day = b.day-1
where a.missed = true and b.missed = true
EDIT
Now that you changed the rules... and made it date and not int in the day column, this is what I'll do:
- Use DAYOFWEEK() function to go to a day as a number
- Filter out weekends
use modulo to get Sunday as the next day of Thursday:
select a.id from yourTable as a inner join yourTable as b on a.id = b.id and DAYOFWEEK(a.day) % 5 = DAYOFWEEK(b.day-1) % 5 where a.missed = true and b.missed = true and DAYOFWEEK(a.day) < 6 and DAYOFWEEK(b.day) < 6
回答2:
similar approach as other answers, but different syntax
select distinct id
from t
where
missed=true and
exists (
select day
from t as t2
where t.id=t2.id and t.day+1=t2.day and t2.missed=true
)
回答3:
This will give you each instance of it happening. You'll get multiple hits if they have 3 or more consecutive days missed, so if that's an issue then you'll need to refine it.
SELECT
T1.id,
T1.day
FROM
My_Table T1
INNER JOIN My_Table T2 ON
T2.id = T1.id AND
T2.day = T1.day + 1 AND
T2.missed = true
WHERE
T1.missed = true
回答4:
You can do it using variables:
SELECT DISTINCT id
FROM (
SELECT day, id, missed,
@rn := IF(@id = id,
IF(missed = true, @rn + 1, 0),
IF(@id := id,
IF(missed = true, 1, 0),
IF(missed = true, 1, 0))) AS rn
FROM mytable
CROSS JOIN (SELECT @rn := 0, @id := 0) AS var
ORDER BY id, day) AS t
WHERE t.rn >= 2
The benefit of the above method is that it is scalable: it can be easily extended to check for more than 2 consecutive records of student absences.
Demo here
回答5:
Here's one way...
SELECT x.id
FROM my_table x
JOIN my_table y
ON y.id = x.id
AND y.missed = x.missed
AND y.day > x.day
AND 5 * (DATEDIFF(y.day, x.day) DIV 7) + MID('0123444401233334012222340111123400001234000123440', 7 * WEEKDAY(x.day) + WEEKDAY(y.day) + 1, 1) <= 1
WHERE x.missed = 1;
来源:https://stackoverflow.com/questions/35419581/how-to-select-where-there-are-2-consecutives-rows-with-a-specific-value-using-my