MySQL 根据日期范围重叠查询 select 不同的行
MySQL query to select distinct rows based on date range overlapping
假设我们有一个 table (table1),我们在其中存储 4 个值 (user_id, name, start_date, end_date)
table1
------------------------------------------------
id user_id name start_date end_date
------------------------------------------------
1 1 john 2016-04-02 2016-04-03
2 2 steve 2016-04-06 2016-04-06
3 3 sarah 2016-04-03 2016-04-03
4 1 john 2016-04-12 2016-04-15
然后我输入 2016-04-03 的 start_date 和 2016-04-03 的 end_date 以查看是否有任何用户可以安排工作。检查并忽略重叠日期的查询 returns 以下内容:
table1
------------------------------------------------
id user_id name start_date end_date
------------------------------------------------
2 2 steve 2016-04-06 2016-04-06
4 1 john 2016-04-12 2016-04-15
我遇到的问题是 John 显示在列表中,即使他已经为我正在搜索的日期预订了工作。另一个条目的查询 returns TRUE 因为日期不冲突,但我想从列表中完全隐藏 John,因为他将不可用。
如果输入的日期与同一用户的另一个条目冲突,是否可以过滤列表并阻止显示用户信息?
查询示例:
SELECT DISTINCT id, user_id, name, start_date, end_date
FROM table1
WHERE ('{$startDate}' NOT BETWEEN start_date AND end_date
AND '{$endDate}' NOT BETWEEN start_date AND end_date
AND start_date NOT BETWEEN '{$startDate}' AND '{$endDate}'
AND end_date NOT BETWEEN '{$startDate}' AND '{$endDate}');
这行得通吗?
SELECT user_id DISTINCT FROM table1 WHERE (DATEDIFF(_input_,start_date) > 0 AND
DATEDIFF(_input_,end_date) > 0) OR
(DATEDIFF(_input_,start_date) < 0);
题目中的"solution"看起来一点都不对
INSERT INTO table1 VALUES (5,2,'steve', '2016-04-01','2016-04-04')
现在和 Steve 发生了冲突。
问题中作为解决方案提出的查询将 return 'steve'。
这里演示了如何针对 return 在请求期间 "available" 的用户构建查询,因为 table1 中没有该用户的行 "overlaps" 与请求的周期。
第一个问题是获取不可用的用户,因为存在与请求时间段重叠的行。假设 start_date <= end_date 对于 table...
中的所有行
如果该行的 end_date 在请求的时间段开始后 或 之后,并且 start_date 行与请求的时间段重叠该行的行在或之前请求的时间段的ed。
-- users that are "unavailable" due to row with overlap
SELECT t.user_id
FROM table1 t
WHERE t.end_date >= '2016-04-03' -- start of requested period
AND t.start_date <= '2016-04-03' -- end of requested_period
GROUP
BY t.user_id
(如果我们的假设 start_date <= end_date 不成立,我们可以在查询中添加该检查作为条件)
要获取所有用户的列表,我们可以查询具有不同用户列表的 table。我们在问题中没有看到这样的 table,因此我们可以获取出现在 table1 中的所有用户的列表,而不是
SELECT l.user_id
FROM table1 l
GROUP BY l.user_id
要获取除不可用用户之外的所有用户的列表,我们可以通过多种方式编写。最简单的是反连接模式:
SELECT a.user_id
FROM ( -- list of all users
SELECT l.user_id
FROM table1 l
GROUP BY l.user_id
) a
LEFT
JOIN ( -- users that are unavailable due to overlap
SELECT t.user_id
FROM table1 t
WHERE t.end_date >= '2016-04-03' -- start of requested period
AND t.start_date <= '2016-04-03' -- end of requested_period
GROUP
BY t.user_id
) u
ON u.user_id = a.user_id
WHERE u.user_id IS NULL
假设我们有一个 table (table1),我们在其中存储 4 个值 (user_id, name, start_date, end_date)
table1
------------------------------------------------
id user_id name start_date end_date
------------------------------------------------
1 1 john 2016-04-02 2016-04-03
2 2 steve 2016-04-06 2016-04-06
3 3 sarah 2016-04-03 2016-04-03
4 1 john 2016-04-12 2016-04-15
然后我输入 2016-04-03 的 start_date 和 2016-04-03 的 end_date 以查看是否有任何用户可以安排工作。检查并忽略重叠日期的查询 returns 以下内容:
table1
------------------------------------------------
id user_id name start_date end_date
------------------------------------------------
2 2 steve 2016-04-06 2016-04-06
4 1 john 2016-04-12 2016-04-15
我遇到的问题是 John 显示在列表中,即使他已经为我正在搜索的日期预订了工作。另一个条目的查询 returns TRUE 因为日期不冲突,但我想从列表中完全隐藏 John,因为他将不可用。
如果输入的日期与同一用户的另一个条目冲突,是否可以过滤列表并阻止显示用户信息?
查询示例:
SELECT DISTINCT id, user_id, name, start_date, end_date
FROM table1
WHERE ('{$startDate}' NOT BETWEEN start_date AND end_date
AND '{$endDate}' NOT BETWEEN start_date AND end_date
AND start_date NOT BETWEEN '{$startDate}' AND '{$endDate}'
AND end_date NOT BETWEEN '{$startDate}' AND '{$endDate}');
这行得通吗?
SELECT user_id DISTINCT FROM table1 WHERE (DATEDIFF(_input_,start_date) > 0 AND
DATEDIFF(_input_,end_date) > 0) OR
(DATEDIFF(_input_,start_date) < 0);
题目中的"solution"看起来一点都不对
INSERT INTO table1 VALUES (5,2,'steve', '2016-04-01','2016-04-04')
现在和 Steve 发生了冲突。
问题中作为解决方案提出的查询将 return 'steve'。
这里演示了如何针对 return 在请求期间 "available" 的用户构建查询,因为 table1 中没有该用户的行 "overlaps" 与请求的周期。
第一个问题是获取不可用的用户,因为存在与请求时间段重叠的行。假设 start_date <= end_date 对于 table...
中的所有行如果该行的 end_date 在请求的时间段开始后 或 之后,并且 start_date 行与请求的时间段重叠该行的行在或之前请求的时间段的ed。
-- users that are "unavailable" due to row with overlap
SELECT t.user_id
FROM table1 t
WHERE t.end_date >= '2016-04-03' -- start of requested period
AND t.start_date <= '2016-04-03' -- end of requested_period
GROUP
BY t.user_id
(如果我们的假设 start_date <= end_date 不成立,我们可以在查询中添加该检查作为条件)
要获取所有用户的列表,我们可以查询具有不同用户列表的 table。我们在问题中没有看到这样的 table,因此我们可以获取出现在 table1 中的所有用户的列表,而不是
SELECT l.user_id
FROM table1 l
GROUP BY l.user_id
要获取除不可用用户之外的所有用户的列表,我们可以通过多种方式编写。最简单的是反连接模式:
SELECT a.user_id
FROM ( -- list of all users
SELECT l.user_id
FROM table1 l
GROUP BY l.user_id
) a
LEFT
JOIN ( -- users that are unavailable due to overlap
SELECT t.user_id
FROM table1 t
WHERE t.end_date >= '2016-04-03' -- start of requested period
AND t.start_date <= '2016-04-03' -- end of requested_period
GROUP
BY t.user_id
) u
ON u.user_id = a.user_id
WHERE u.user_id IS NULL