如何在 MySQL 中找到缺失的日期和班次?
How to find missing date and shift in MySQL?
我的 MySQL table:
中有三列
id | date | shift
-----+------------+---------
52 | 2017-01-01 | 1
51 | 2017-01-01 | 2
51 | 2017-01-01 | 3
51 | 2017-01-02 | 1
51 | 2017-01-02 | 3
51 | 2017-01-03 | 1
51 | 2017-01-03 | 2
51 | 2017-01-05 | 1
51 | 2017-01-05 | 2
51 | 2017-01-05 | 3
在此table中缺少两个班次; 2017-01-02
的第 2 班和 2017-01-03
的第 3 班。和 2017-01-04 日期完全错过了那么我如何通过 MySQL 查询找到它?
我想要找到 id='51' 位置的条件
那么结果是 2017-01-01
中也缺少第一班
并且还发现错过了 27 天并显示 27 个日期。
请帮助我。
一种方法是制作所有可接受的行,然后像这样过滤当前行:
select *
from (
select `date`
from `yourTable`
group by `date`) as `td` -- gathering unique data
cross join (
select 1 `shift`
union all select 2
union all select 3) as `ts` -- generating a source for shifts
-- filtering those are not exists in current rows
where not exists (
select 1 from `yourTable` as `ti`
where `ti`.`date` = `td`.`date` and `ti`.`shift` = `ts`.`shift`);
更新:
你在评论中的问题可以这样回答:
select *
from (
select *
from (
select `id`, `date` -- <= added `id`
from `yourTable`
group by `id`, `date`) as `td` -- gathering unique data <= added `id`
cross join (
select 1 `shift`
union all select 2
union all select 3) as `ts` -- generating a source for shifts
where not exists (
select 1 from `yourTable` as `ti`
-- filtering those are not exists in current rows
where `ti`.`date` = `td`.`date`
and `ti`.`id` = `td`.`id` -- <= added `id` filter
and `ti`.`shift` = `ts`.`shift`)
) as `t`
where `id` = 51; -- <= now you can filter over its result
更新:
当您再次更改问题时:
select *
from (
select *
from (
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where a.Date between '2017-01-01' and '2017-01-04'
) as `td` -- gathering unique data
cross join (
select 1 `shift`
union all select 2
union all select 3) as `ts` -- generating a source for shifts
where not exists (
select 1 from `yourTable` as `ti`
-- filtering those are not exists in current rows
where `ti`.`date` = `td`.`date`
and `ti`.`id` = 51
and `ti`.`shift` = `ts`.`shift`)
) as `t`;
我的 MySQL table:
中有三列id | date | shift
-----+------------+---------
52 | 2017-01-01 | 1
51 | 2017-01-01 | 2
51 | 2017-01-01 | 3
51 | 2017-01-02 | 1
51 | 2017-01-02 | 3
51 | 2017-01-03 | 1
51 | 2017-01-03 | 2
51 | 2017-01-05 | 1
51 | 2017-01-05 | 2
51 | 2017-01-05 | 3
在此table中缺少两个班次; 2017-01-02
的第 2 班和 2017-01-03
的第 3 班。和 2017-01-04 日期完全错过了那么我如何通过 MySQL 查询找到它?
我想要找到 id='51' 位置的条件
那么结果是 2017-01-01
中也缺少第一班
并且还发现错过了 27 天并显示 27 个日期。
请帮助我。
一种方法是制作所有可接受的行,然后像这样过滤当前行:
select *
from (
select `date`
from `yourTable`
group by `date`) as `td` -- gathering unique data
cross join (
select 1 `shift`
union all select 2
union all select 3) as `ts` -- generating a source for shifts
-- filtering those are not exists in current rows
where not exists (
select 1 from `yourTable` as `ti`
where `ti`.`date` = `td`.`date` and `ti`.`shift` = `ts`.`shift`);
更新:
你在评论中的问题可以这样回答:
select *
from (
select *
from (
select `id`, `date` -- <= added `id`
from `yourTable`
group by `id`, `date`) as `td` -- gathering unique data <= added `id`
cross join (
select 1 `shift`
union all select 2
union all select 3) as `ts` -- generating a source for shifts
where not exists (
select 1 from `yourTable` as `ti`
-- filtering those are not exists in current rows
where `ti`.`date` = `td`.`date`
and `ti`.`id` = `td`.`id` -- <= added `id` filter
and `ti`.`shift` = `ts`.`shift`)
) as `t`
where `id` = 51; -- <= now you can filter over its result
更新:
当您再次更改问题时:
select *
from (
select *
from (
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where a.Date between '2017-01-01' and '2017-01-04'
) as `td` -- gathering unique data
cross join (
select 1 `shift`
union all select 2
union all select 3) as `ts` -- generating a source for shifts
where not exists (
select 1 from `yourTable` as `ti`
-- filtering those are not exists in current rows
where `ti`.`date` = `td`.`date`
and `ti`.`id` = 51
and `ti`.`shift` = `ts`.`shift`)
) as `t`;