IMO 选项#1 会更好。加入推文和转推表的查询一点也不复杂,可以通过左连接或内连接来完成,具体取决于您是要显示所有推文还是只显示被转推的推文。并且连接查询应该是高性能的,因为表很窄,被连接的列是整数,并且由于 FK 约束,它们每个都有索引。
另一个建议是不要用 tweet 或 retweet 标记所有列,这些可以从存储数据的表中推断出来,例如:
tweet
id
user_id
text
created_at
retweet
tweet_id
user_id
created_at
样本加入:
# Return all tweets which have been retweeted
SELECT
count(*),
t.id
FROM
tweet AS t
INNER JOIN retweet AS rt ON rt.tweet_id = t.id
GROUP BY
t.id
# Return tweet and possible retweet data for a specific tweet
SELECT
t.id
FROM
tweet AS t
LEFT OUTER JOIN retweet AS rt ON rt.tweet_id = t.id
WHERE
t.id = :tweetId
-- 根据请求更新 --
以下只是说明性的,代表我为什么选择选项#1,没有外键也没有任何索引,您必须自己添加这些。但结果应该表明连接不会太痛苦。
CREATE TABLE `tweet` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`value` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
CREATE TABLE `retweet` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`tweet_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
# Sample Rows
mysql> select * from tweet;
+----+---------+----------------+---------------------+
| id | user_id | value | created_at |
+----+---------+----------------+---------------------+
| 1 | 1 | User1 | Tweet1 | 2012-07-27 00:04:30 |
| 2 | 1 | User1 | Tweet2 | 2012-07-27 00:04:35 |
| 3 | 2 | User2 | Tweet1 | 2012-07-27 00:04:47 |
| 4 | 3 | User3 | Tweet1 | 2012-07-27 00:04:58 |
| 5 | 1 | User1 | Tweet3 | 2012-07-27 00:06:47 |
| 6 | 1 | User1 | Tweet4 | 2012-07-27 00:06:50 |
| 7 | 1 | User1 | Tweet5 | 2012-07-27 00:06:54 |
+----+---------+----------------+---------------------+
mysql> select * from retweet;
+----+----------+---------+---------------------+
| id | tweet_id | user_id | created_at |
+----+----------+---------+---------------------+
| 1 | 4 | 1 | 2012-07-27 00:06:37 |
| 2 | 3 | 1 | 2012-07-27 00:07:11 |
+----+----------+---------+---------------------+
# Query to pull all tweets for user_id = 1, including retweets and order from newest to oldest
select * from (
select t.* from tweet as t where user_id = 1
union
select t.* from tweet as t where t.id in (select tweet_id from retweet where user_id = 1))
a order by created_at desc;
mysql> select * from (select t.* from tweet as t where user_id = 1 union select t.* from tweet as t where t.id in (select tweet_id from retweet where user_id = 1)) a order by created_at desc;
+----+---------+----------------+---------------------+
| id | user_id | value | created_at |
+----+---------+----------------+---------------------+
| 7 | 1 | User1 | Tweet5 | 2012-07-27 00:06:54 |
| 6 | 1 | User1 | Tweet4 | 2012-07-27 00:06:50 |
| 5 | 1 | User1 | Tweet3 | 2012-07-27 00:06:47 |
| 4 | 3 | User3 | Tweet1 | 2012-07-27 00:04:58 |
| 3 | 2 | User2 | Tweet1 | 2012-07-27 00:04:47 |
| 2 | 1 | User1 | Tweet2 | 2012-07-27 00:04:35 |
| 1 | 1 | User1 | Tweet1 | 2012-07-27 00:04:30 |
+----+---------+----------------+---------------------+
请注意,在最后一组结果中,我们还能够包含转推并在 #3 转推之前显示 #4 的转推。
- 更新 -
您可以通过稍微更改查询来完成您的要求:
select * from (
select t.id, t.value, t.created_at from tweet as t where user_id = 1
union
select t.id, t.value, rt.created_at from tweet as t inner join retweet as rt on rt.tweet_id = t.id where rt.user_id = 1)
a order by created_at desc;
mysql> select * from (select t.id, t.value, t.created_at from tweet as t where user_id = 1 union select t.id, t.value, rt.created_at from tweet as t inner join retweet as rt on rt.tweet_id = t.id where rt.user_id = 1) a order by created_at desc;
+----+----------------+---------------------+
| id | value | created_at |
+----+----------------+---------------------+
| 3 | User2 | Tweet1 | 2012-07-27 00:07:11 |
| 7 | User1 | Tweet5 | 2012-07-27 00:06:54 |
| 6 | User1 | Tweet4 | 2012-07-27 00:06:50 |
| 5 | User1 | Tweet3 | 2012-07-27 00:06:47 |
| 4 | User3 | Tweet1 | 2012-07-27 00:06:37 |
| 2 | User1 | Tweet2 | 2012-07-27 00:04:35 |
| 1 | User1 | Tweet1 | 2012-07-27 00:04:30 |
+----+----------------+---------------------+