样本数据库设计
USERS WORKDAYS DAYS
[id] [name] [user_id] [day_id] [id] [name]
1 john 1 2 1 sunday
2 fred 1 3 2 monday
3 bert 1 4 3 tuesday
4 harry 1 5 4 wednesday
1 6 5 thursday
2 2 6 friday
4 1 7 saturday
4 2
4 3
4 4
4 5
4 6
4 7
我将如何查询
我在一段时间内使用mysql,但目前找不到解决方案。通常,我会为此使用位标志,但是我尝试掌握SQL中更规范的解决方案。
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `days` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
CREATE TABLE `workdays` (
`user_id` int(11) NOT NULL,
`day_id` int(11) NOT NULL,
KEY `workdays_users_FK` (`user_id`),
KEY `workdays_days_FK` (`day_id`),
CONSTRAINT `workdays_days_FK` FOREIGN KEY (`day_id`) REFERENCES `days` (`id`),
CONSTRAINT `workdays_users_FK` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO play.users
(id, name)
VALUES(1, 'john');
INSERT INTO play.users
(id, name)
VALUES(2, 'fred');
INSERT INTO play.users
(id, name)
VALUES(3, 'bert');
INSERT INTO play.users
(id, name)
VALUES(4, 'harry');
INSERT INTO play.days
(id, name)
VALUES(1, 'sunday');
INSERT INTO play.days
(id, name)
VALUES(2, 'monday');
INSERT INTO play.days
(id, name)
VALUES(3, 'tuesday');
INSERT INTO play.days
(id, name)
VALUES(4, 'wednesday');
INSERT INTO play.days
(id, name)
VALUES(5, 'thursday');
INSERT INTO play.days
(id, name)
VALUES(6, 'friday');
INSERT INTO play.days
(id, name)
VALUES(7, 'saturday');
INSERT INTO play.workdays
(user_id, day_id)
VALUES(1, 2);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(1, 3);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(1, 4);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(1, 5);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(1, 6);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(2, 2);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(4, 1);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(4, 2);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(4, 3);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(4, 4);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(4, 5);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(4, 6);
INSERT INTO play.workdays
(user_id, day_id)
VALUES(4, 7);
答案 0 :(得分:1)
GROUP BY
输入用户名和用户名。HAVING
子句与SUM()
聚合一起使用以过滤掉案例。SUM()
将为零,然后加入。对于第一种情况(完全在一周中的所有工作日均可正常运行),请尝试:
SELECT u.id, u.name
FROM USERS AS u
JOIN WORKDAYS AS wd ON wd.user_id = u.id
JOIN DAYS AS d ON d.id = wd.day_id
GROUP BY u.id, u.name
HAVING SUM(d.name = 'monday')
AND SUM(d.name = 'tuesday')
AND SUM(d.name = 'wednesday')
AND SUM(d.name = 'thursday')
AND SUM(d.name = 'friday')
AND SUM(d.name = 'sunday') = 0
AND SUM(d.name = 'saturday') = 0
对于第二种情况,只需删除sunday
和saturday
上的条件。试试:
SELECT u.id, u.name
FROM USERS AS u
JOIN WORKDAYS AS wd ON wd.user_id = u.id
JOIN DAYS AS d ON d.id = wd.day_id
GROUP BY u.id, u.name
HAVING SUM(d.name = 'monday')
AND SUM(d.name = 'tuesday')
AND SUM(d.name = 'wednesday')
AND SUM(d.name = 'thursday')
AND SUM(d.name = 'friday')
答案 1 :(得分:1)
一整天之后,我都会做:
SELECT u.id, u.name
FROM USERS u JOIN
WORKDAYS wd
ON wd.user_id = u.id JOIN
DAYS d
ON d.id = wd.day_id
GROUP BY u.id, u.name
HAVING SUM(d.name = 'monday') > 0 AND
SUM(d.name = 'tuesday') > 0 AND
SUM(d.name = 'wednesday') > 0 AND
SUM(d.name = 'thursday') > 0 AND
SUM(d.name = 'friday') > 0;
或者:
SELECT u.id, u.name
FROM USERS u JOIN
WORKDAYS wd
ON wd.user_id = u.id JOIN
DAYS d
ON d.id = wd.day_id
WHERE d.name IN ('monday', 'tuesday', 'wednesday', 'thursday', 'friday')
GROUP BY u.id, u.name
HAVING COUNT(DISTINCT d.name) = 5
确切的那几天,没有其他人:
SELECT u.id, u.name
FROM USERS u JOIN
WORKDAYS wd
ON wd.user_id = u.id JOIN
DAYS d
ON d.id = wd.day_id
GROUP BY u.id, u.name
HAVING SUM(d.name = 'monday') > 0 AND
SUM(d.name = 'tuesday') > 0 AND
SUM(d.name = 'wednesday') > 0 AND
SUM(d.name = 'thursday') > 0 AND
SUM(d.name = 'friday') > 0 AND
SUM(d.name NOT IN ('monday', 'tuesday', 'wednesday', 'thursday', 'friday')) = 0
答案 2 :(得分:1)
如果您希望在1个查询中使用它,
select
id,
name,
group_concat(distinct w.day_id order by w.day_id) worked
from
users u
join workdays w on
u.id = w.user_id
group by
id,
name
having
worked like '%2,3,4,5,6%' // or worked ='2,3,4,5,6'
id |name |worked |
---|------|--------------|
1 |john |2,3,4,5,6 |
4 |harry |1,2,3,4,5,6,7 |
请注意,我为此使用了自己的用户表