如何从可选联结表的多对多关系中进行选择?

时间:2017-02-23 16:33:22

标签: mysql

我有一个用户设置设置,其中包含一个所谓的'属性包'我猜。 我想存储我的用户的设置。大多数用户都不会更改默认设置,所以我认为我应该制作一个默认值'对于每个设置。这样我就不会为每个用户存储每个设置的user_setting记录。

这是我的(简化的)mysql数据库:

CREATE TABLE `user` (
  `user_id` INT NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`user_id`)
);

CREATE TABLE `setting` (
  `setting_id` INT NOT NULL AUTO_INCREMENT,
  `key` VARCHAR(100) NOT NULL,
  `default_value` VARCHAR(100) NOT NULL,
  PRIMARY KEY (`setting_id`)
);  

CREATE TABLE `user_setting` (
  `user_setting_id` INT NOT NULL AUTO_INCREMENT,
  `user_id` INT NOT NULL,
  `setting_id` INT NOT NULL,
  `value` VARCHAR(100) NOT NULL,
  PRIMARY KEY (`user_setting_id`),
  CONSTRAINT `fk_user_setting_1`
    FOREIGN KEY (`user_id`)
    REFERENCES `user` (`user_id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `fk_user_setting_2`
    FOREIGN KEY (`setting_id`)
    REFERENCES `setting` (`setting_id`)
    ON DELETE RESTRICT
    ON UPDATE CASCADE
);

INSERT INTO `user` VALUES (1, 'username1'),(2, 'username2');
INSERT INTO `setting` VALUES (1, 'key1', 'somevalue'),(2, 'key2', 'someothervalue');

在我的代码中,我可以轻松查找每个用户的每个设置。通过检查user_setting表中是否有一行,我知道这是默认值。

但有没有办法概述每个用户的所有设置? Normaly我会离开加入用户 - > user_setting - >为每个用户设置表格,但现在我没有为每个用户/设置设置user_setting记录。单个查询可以实现吗?

2 个答案:

答案 0 :(得分:1)

如果您刚刚usersetting进行了笛卡尔联接,则每个用户/设置组合都会获得一行。然后只需左键加入user_setting表,就可以在存在时获取被覆盖的值。

这样的事情:

SELECT u.user_id, s.key, s.default_value, us.value 
FROM user u, setting s
LEFT JOIN user_setting us 
  ON(us.user_id=u.user_id AND us.setting_id=s.setting_id)
ORDER BY u.user_id, s.key

您可以使用IFNULL进一步优化此设置,以便获取设置的值,无论它是否被覆盖或默认:

SELECT u.user_id, s.key, IFNULL(us.value , s.default_value) AS value
FROM user u, setting s
LEFT JOIN user_setting us 
  ON(us.user_id=u.user_id AND us.setting_id=s.setting_id)
ORDER BY u.user_id, s.key

答案 1 :(得分:0)

(回答我自己的问题不是我正常工作的方式,但我不确定这是否是正确的答案,而且它是基于Paul Dixon的回答)

如上所述,用户和设置之间需要进行笛卡尔连接。正确的查询是:

SELECT u.user_id, s.key, IFNULL(us.value , s.default_value) AS value
FROM user u 
CROSS JOIN setting s 
LEFT JOIN user_setting us ON
(us.user_id=u.user_id AND us.setting_id=s.setting_id) 
ORDER BY u.user_id, s.key;