[英]MySQL query to select distinct rows based on date range overlapping
Let's say we have a table (table1) in which we store 4 values (user_id, name, start_date, end_date) 假设我们有一个表(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
I then enter a start_date of 2016-04-03 and end_date of 2016-04-03 to see if any of the users are available to be scheduled for a job. 然后,我输入2016-04-03的start_date和2016-04-03的end_date,以查看是否有任何用户可以安排作业。 The query that checks for and ignores overlapping dates returns the following: 检查并忽略重叠日期的查询返回以下内容:
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
The issue I am having is that John is being displayed on the list even though he is already booked for a job for the dates I am searching for. 我遇到的问题是John正在列表中显示,即使他已经预订了我正在搜索的日期的工作。 The query returns TRUE for the other entry because the dates don't conflict, but i would like to hide John from the list completely since he will be unavailable. 查询为其他条目返回TRUE,因为日期不冲突,但我想完全隐藏John列表,因为他将不可用。
Is there a way to filter the list and prevent the user info from displaying if the dates entered conflict with another entry for the same user? 有没有办法过滤列表,如果输入的日期与同一用户的另一个条目冲突,是否阻止显示用户信息?
An example of the query: 查询示例:
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}');
will this work? 这会有用吗?
SELECT user_id DISTINCT FROM table1 WHERE (DATEDIFF(_input_,start_date) > 0 AND
DATEDIFF(_input_,end_date) > 0) OR
(DATEDIFF(_input_,start_date) < 0);
The "solution" in the question doesn't look right at all. 问题中的“解决方案”看起来并不正确。
INSERT INTO table1 VALUES (5,2,'steve', '2016-04-01','2016-04-04')
Now there's a row with Steve having an overlap. 现在史蒂夫有一个重叠的行。
And the query proposed as a SOLUTION in the question will return 'steve'. 在问题中作为解决方案提出的查询将返回'steve'。
Here's a demonstration of building a query to return the users that are "available" during the requested period, because there is no row in table1 for that user that "overlaps" with the requested period. 以下是构建查询以返回在请求的时间段内“可用”的用户的演示,因为table1中没有该行与请求的时段“重叠”的行。
First problem is getting the users that are not available due to the existence of a row that overlaps the requested period. 第一个问题是由于存在与请求的时间段重叠的行而导致用户不可用。 Assuming that start_date <= end_date for all rows in the table... 假设表中所有行的start_date <= end_date ...
A row overlaps the requested period, if the end_date of the row is on or after the start of the requested period, and the start_date of the row is on or before the ed of the requested period. 如果行的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
(If our assumption that start_date <= end_date doesn't hold, we can add that check as a condition in the query) (如果我们假设start_date <= end_date不成立,我们可以将该检查添加为查询中的条件)
To get a list of all users, we could query a table that has a distinct list of users. 要获取所有用户的列表,我们可以查询具有不同用户列表的表。 We don't see a table like that in the question, so we can get a list of all users that appear in table1 instead 我们在问题中没有看到这样的表格,因此我们可以获得表格1中出现的所有用户的列表
SELECT l.user_id
FROM table1 l
GROUP BY l.user_id
To get the list of all users excluding the users that are unavailable, there are couple of ways we can write that. 要获取除不可用用户之外的所有用户的列表,我们可以通过以下几种方式编写该用户。 The simplest is an anti-join pattern: 最简单的是反连接模式:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.