SQL Query从所有用户的朋友检索消息

时间:2013-02-17 21:49:40

标签: mysql sql database database-design

我为Twitter克隆网站设置了3个数据库。

表'用户':

email | firstname | lastname | hash_password

链接表'朋友':

email | friend

列出了所有用户及其朋友。友谊是单向的(如Twitter的“关注”/“追随者”)。 friends表是一个列出所有用户朋友的链接表。因此,friends.userfriends.friend都是users.email的外键。

表'消息':

timestamp | user | content

什么是用于检索用户及其朋友的所有消息的SQL查询?


我试过了:

SELECT
  'timestamp', 
  user, 
  content 
FROM
  messages
  INNER JOIN friends ON messages.user = friends.friend
ORDER BY 'timestamp' DESC;

这似乎正确加入了它们,但我怎样才能获取特定用户(电子邮件地址)朋友的消息。现在,这只会返回所有消息。

感谢。

1 个答案:

答案 0 :(得分:2)

timestamp的引用应该是反引号,否则MySQL将采用字符串文字值。

否则,要返回来自用户和所有朋友的消息,您可以使用UNION。一半返回用户的消息,另一半返回朋友的消息。您需要将用户的电子邮件添加到您的加入条件:

/* First part of the UNION returns friends messages */
SELECT
  `timestamp`, 
  user, 
  content 
FROM
  messages 
  /* The join ON clause specifies the main user email */
  INNER JOIN friends 
    ON messages.user = friends.friend
       AND friends.email = 'email@example.com'
UNION ALL
/* Other part of the UNION just gets all messages for the main user by email addr */
SELECT
  `timestamp`,
  user,
  content
FROM
  messages
WHERE user = 'email@example.com'
/* ORDER BY applies to everything */
ORDER BY `timestamp` DESC;

如果您想在此处加入users信息(firstname/lastname),最简单的方法是将整个事物包装在子查询中并加入。

SELECT
  users.*,
  messages_sub.content,
  messages_sub.`timestamp`
FROM
  users
  JOIN (/* The entire thing from above */) AS messages_sub ON users.email = messages_sub.user
ORDER BY `timestamp`

也可以使用您要查找的文字电子邮件地址的UNION和朋友列表来完成,只生成一个外部查询。这有点棘手,但可能最终会更快。从users表中引入其他列也不会引起混淆。我将添加名称:

SELECT
  `timestamp`,
  user,
  firstname,
  lastname,
  content
FROM
  messages
  INNER JOIN (
    /* Union query produces a list of email addrs - 
       the person you're looking for plus all his friends
       Starts with string literal for the main user
    */
    SELECT 'email@example.com' AS email
    UNION 
    /* Plus all his friends into one list joined against messages */
    SELECT friend AS email FROM friends WHERE email = 'email@example.com'
  ) user_and_friends ON messages.user = user_and_friends.email
  /* Join against the users table for name info */
  INNER JOIN users ON user_and_friends.email = users.email
ORDER BY `timestamp` DESC