[英]Mysql Left Join with Group By and Between
I am having trouble to create a select query that will retrieve all users id that isn't in the games and availability between dates. 我无法创建一个选择查询,该查询将检索游戏中不存在的所有用户ID以及日期之间的可用性。
Example: Retrieve all users that are not between dates 2017-08-10
and 2017-08-12
. 示例:检索不在
2017-08-10
和2017-08-12
之间的所有用户。
Get [3 , 4, 5]
获得
[3 , 4, 5]
Users 用户
| Id | Name |
| 1 | Jonh |
| 2 | Mark |
| 3 | Caroline |
| 4 | David |
| 5 | George |
Games 游戏
| Id | User_Id | Start_Date | End_Date |
| 1 | 1 | 2017-06-01 | 2017-06-01 |
| 2 | 1 | 2017-08-12 | 2017-08-13 |
| 3 | 4 | 2017-08-13 | 2017-08-14 |
Availability 可用性
| Id | User_Id | Start_Date | End_Date |
| 1 | 1 | 2017-05-01 | 2017-05-25 |
| 1 | 2 | 2017-08-10 | 2017-08-17 |
| 1 | 3 | 2017-06-20 | 2017-07-10 |
I am using Laravel 5.4 but I'll glad if the answer is on Raw or Eloquent. 我正在使用Laravel 5.4,但如果答案是Raw或Eloquent,我会很高兴的。
In SQL, you can use NOT EXISTS
: 在SQL中,您可以使用
NOT EXISTS
:
select *
from users u
where not exists (
select 1
from games g
where u.id = g.user_id
and (
g.start_date between '2017-08-10' and '2017-08-12'
or g.end_date between '2017-08-10' and '2017-08-12'
)
)
and not exists (
select 1
from Availability a
where u.id = a.user_id
and (
a.start_date between '2017-08-10' and '2017-08-12'
or a.end_date between '2017-08-10' and '2017-08-12'
)
);
Another way using LEFT JOIN
would be: 使用
LEFT JOIN
另一种方法是:
select distinct u.*
from t_users u
left join games g on u.id = g.user_id
and (g.start_date between '2017-08-10' and '2017-08-12'
or g.end_date between '2017-08-10' and '2017-08-12')
left join availability a on u.id = a.user_id
and (a.start_date between '2017-08-10' and '2017-08-12'
or a.end_date between '2017-08-10' and '2017-08-12')
where g.user_id is null and a.user_id is null;
I dont like using human readable dates because of MMDDYYYY vs DDMMYYYY, but rather use UNIXTIME dates, so i will pseudocode accordingly 因为MMDDYYYY和DDMMYYYY,我不喜欢使用人类可读的日期,而是使用UNIXTIME日期,所以我将相应地伪代码
SELECT *
FROM Users
LEFT JOIN Games ON Users.Id = Games.Id_User
LEFT JOIN Availability ON Users.Id = Availability.Id_User
WHERE ISNULL(Games.Id) AND ((Start_Date > EndDateUnixtime OR End_Date < StartDateUnixtime) OR ISNULL(Start_Date) OR ISNULL(End_Date))
You can use this logic to convert DMMYYYY dates to unixtime in case you keep on recording human readable dates. 如果继续记录人类可读日期,您可以使用此逻辑将DMMYYYY日期转换为unixtime。
unix_timestamp(str_to_date('30/05/2011','%d/%m/%Y'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.