我有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
再次感谢你的时间。
答案 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号房间时匹配。