MySQL query to select distinct rows based on date range overlapping

放肆的年华 提交于 2021-02-11 01:33:24

问题


Let's say we have a table (table1) in which we store 4 values (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. 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. 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.

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}');

回答1:


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'.


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.

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...

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.

-- 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)

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

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



回答2:


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);


来源:https://stackoverflow.com/questions/36928840/mysql-query-to-select-distinct-rows-based-on-date-range-overlapping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!