mysql - 如何通过数据透视表选择具有一定关系的行?

标签 mysql sql

示例数据库设计

  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

如何查询

  1. 像 John 这样的人,他完全一周的所有工作日都在工作:周一、周二、周三、周四、周五
  2. 有人像哈利和约翰那样至少一直在工作吗?

我有一段时间使用 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);

最佳答案

  • 您可以根据用户 ID 和名称GROUP BY
  • 使用 HAVING 子句和 SUM() 聚合来过滤案例。
  • 如果用户在某一天不工作,那一天的 SUM() 将为零,post joins。

对于第一种情况(在一周的所有工作日完全工作),尝试:

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

对于第二种情况,只需删除星期日星期六 的条件。尝试:

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

关于mysql - 如何通过数据透视表选择具有一定关系的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52837058/

相关文章:

php - Magento 不获取新的数据库详细信息

php - 循环查找 MySQL 中的日期

mysql - mysql 的 Django BooleanField 默认值

php - 使用 php 问题删除 mysql 上的一行

sql - 在 VB.NET 中搜索 DataGridView 的最佳方式?

php - Valum php AJAX 上传 : Store File Name and Path into mySQL database

mysql - 某航空培训中心数据库设计与查询

sql - 为主键选择数据类型时应该考虑什么?

mysql - SQL 检查一列中的重复项并删除另一列

SQL 总结时间范围内的最小/最大事件