MySQL数据库JOIN表和搜索WHERE <multiple-columns> </multiple-columns>

时间:2014-02-11 15:38:35

标签: mysql sql database join

我有3个表推文会议室 room_tweet

       tweet                    room                          room_tweet
+----+------+-----+     +----+------+-----+     +----+---------+----------+----------+
| id | text | ... |     | id | name | ... |     | id | room_id | tweet_id | disabled |
+----+------+-----+     +----+------+-----+     +----+---------+----------+----------+
| 10 | a... | ... |     | 20 | a... | ... |     | 80 |   20    |    10    |     1    |
| 11 | b... | ... |     | 21 | b... | ... |     | 81 |   20    |    11    |     0    |
| 12 | c... | ... |     | 22 | c... | ... |     | 82 |   21    |    10    |     1    |
| 13 | d... | ... |     +----+------+-----+     | 83 |   20    |    12    |     1    |
+----+------+-----+                             | 84 |   22    |    10    |     0    |
                                                | 85 |   21    |    11    |     1    |
                                                +----+---------+----------+----------+

我需要一个获取所有推文的查询,并在特定的会议室中显示已禁用状态。

所有推文都显示在所有会议中,每个推文都有已停用状态,每个推文不同会议(同一推文在每个会议室中有不同的禁用状态)这是通过 room_tweet实现的表。

这是我到目前为止所写的查询:

SELECT t.id AS tweet_id, t.text AS tweet, rt.disabled, r.id AS room_id, r.name AS room  
FROM tweet as t 
LEFT JOIN room_tweet as rt ON t.id = rt.tweet_id 
LEFT JOIN room as r ON rt.room_id = r.id
WHERE r.id = 21 OR r.id IS NULL

并非所有推文都在 room_tweet 表格中,以便将它们与会议室相关联。因此,许多推文会对结果集中的空间进行 NULL 引用,同样适用于会议室,某些会议室不会与他们相关联推文。 [这并不意味着推文不应出现在结果集上。]

所有推文应出现在结果集一次(仅一次),禁用状态为[1,0或NULL]

如果所有推文碰巧在 room_tweet 表上都有关联,那将是一个简单的查询,但事实并非如此。由于推文是全天创建的,会议室是随机创建的,因此 room_tweet 表不会,也不应该包含所有关联。

Result without WHERE:
+----------+-------+----------+---------+------+
| tweet_id | tweet | disabled | room_id | room |
+----------+-------+----------+---------+------+
|    10    | a...  |    1     |    20   | a... |
|    10    | a...  |    1     |    21   | b... |
|    10    | a...  |    0     |    22   | c... |
|    11    | b...  |    0     |    20   | a... |
|    11    | b...  |    1     |    21   | b... |
|    12    | c...  |    1     |    20   | a... |
|    13    | d...  |   NULL   |   NULL  | NULL |
+----------+-------+----------+---------+------+
Tweets are duplicated multiple times ex: tweet 10 shows 3 times.

Result with (WHERE r.id = 21 OR r.id IS NULL)
+----------+-------+----------+---------+------+
| tweet_id | tweet | disabled | room_id | room |
+----------+-------+----------+---------+------+
|    10    | a...  |    1     |    21   | b... |
|    11    | b...  |    1     |    21   | b... |
|    13    | d...  |   NULL   |   NULL  | NULL |
+----------+-------+----------+---------+------+    
Tweets are missing!, only tweet with id 10, 11 and 13 show up. This is because 
the other tweets have been associated with other rooms and therefore are not 
**NULL** anymore. (All tweets should appear once).

正如您在结果集中看到的那样,并非显示所有推文(当使用 WHERE 时)而另一个问题 room_tweet 表中与多个会议室关联的推文,因此它们在结果集上重复。 (我只想看一次推文一次!)

所以问题是:我在查询上缺少什么,甚至可能获得我期待的结果

是否可以解决此问题?如果是这样,我的查询是问题还是表错了?

如果你想在这里测试查询是在phpMyAdmin中创建所有表和数据的SQL:

CREATE TABLE `room` (`id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(60) NOT NULL, `...` varchar(3) NOT NULL DEFAULT '...', PRIMARY KEY (`id`) ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=23 ;
CREATE TABLE `tweet` (`id` int(11) NOT NULL AUTO_INCREMENT, `text` varchar(140) NOT NULL, `...` varchar(3) NOT NULL DEFAULT '...', PRIMARY KEY (`id`) ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=14 ;
CREATE TABLE `room_tweet` (`id` int(11) NOT NULL AUTO_INCREMENT, `room_id` int(11) NOT NULL, `tweet_id` int(11) NOT NULL, `disabled` tinyint(1) NOT NULL, PRIMARY KEY (`id`), KEY `fk_room_tweet_1` (`room_id`), KEY `fk_room_tweet_2` (`tweet_id`) ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=86 ;
ALTER TABLE `room_tweet` ADD CONSTRAINT `fk_room_tweet_1` FOREIGN KEY (`room_id`) REFERENCES `room` (`id`), ADD CONSTRAINT `fk_room_tweet_2` FOREIGN KEY (`tweet_id`) REFERENCES `tweet` (`id`);    
INSERT INTO `room` (`id`, `name`, `...`) VALUES (20, 'a...', '...'), (21, 'b...', '...'), (22, 'c...', '...');    
INSERT INTO `tweet` (`id`, `text`, `...`) VALUES (10, 'a...', '...'), (11, 'b...', '...'), (12, 'c...', '...'), (13, 'd...', '...');
INSERT INTO `room_tweet` (`id`, `room_id`, `tweet_id`, `disabled`) VALUES (80, 20, 10, 1), (81, 20, 11, 0), (82, 21, 10, 1), (83, 20, 12, 1), (84, 22, 10, 0), (85, 21, 11, 1);

我尝试过JOIN,INNER JOIN,LEFT JOIN,RIGHT JOIN,中午似乎解决了我的问题。

感谢您的时间,再次,我唯一需要的是结果集,它会显示推文,以显示已停用说明具体的房间。如果没有禁用状态,则应显示 NULL

到目前为止,最好的结果是:

SELECT t.id AS tweet_id, t.text AS tweet, rt.disabled, r.id AS room_id, r.name AS room  
FROM tweet as t 
LEFT JOIN room_tweet as rt ON t.id = rt.tweet_id 
LEFT JOIN room as r ON rt.room_id = r.id

再次感谢你的时间。

1 个答案:

答案 0 :(得分:0)

您需要将r.id条件移至on子句:

SELECT t.id AS tweet_id, t.text AS tweet, rt.disabled, r.id AS room_id, r.name AS room  
FROM tweet as t 
LEFT JOIN room_tweet as rt ON t.id = rt.tweet_id 
LEFT JOIN room as r ON rt.room_id = r.id and r.id = 21;

使用此查询,事物只会在他们在21号房间时匹配。