【问题标题】:Mysql query of Facebook style wallFacebook风格墙的mysql查询
【发布时间】:2011-10-18 12:31:09
【问题描述】:

我想在我的网站上创建会员墙(facebook 风格)。 基于:

  • 会员好友的最后一集。
  • 会员朋友的最后档案。
  • 成员文件的最后一个 cmets。

表结构:

friendship
userid | friendid | status
---------------------------------
user_table
userid | username
---------------------------------
files_table
file_id | file_title | file_desc | dl_date
---------------------------------
comments_table
comid | userid | file_id | com_date

这是我的 mysql 查询,它有效。但我想知道你的想法,让它变得更好。

--Last files of member's friends
-- Find files of friendship.friendid=$userid
SELECT files_table.file_id AS c1, files_table.file_title AS c2, files_table.file_desc AS c3, files_table.dlauthor AS c4, files_table.dl_date AS date,  IF(files_table.file_id IS NOT NULL, 'Friends_eBooks',FALSE) as Type
    FROM friendship
    LEFT JOIN user_table ON friendship.userid = user_table.userid
    LEFT JOIN files_table ON files_table.dlauthor = user_table.username
    WHERE friendship.friendid = $userid
    AND friendship.STATUS = '1'
-- Find files of friendship.userid=$userid
UNION
SELECT files_table.file_id AS c1, files_table.file_title AS c2, files_table.file_desc AS c3, files_table.dlauthor AS c4, files_table.dl_date AS date,  IF(files_table.file_id IS NOT NULL, 'Friends_eBooks',FALSE) as Type
    FROM friendship
    LEFT JOIN user_table ON friendship.userid = user_table.userid
    LEFT JOIN files_table ON files_table.dlauthor = user_table.username
    WHERE friendship.userid = $userid
    AND friendship.STATUS = '1'
UNION ALL
-- Last comments of member's friends
-- Find comments of friendship.friendid=$userid
SELECT comments_table.comid AS c1, user_table.username AS c2, comments_table.dl_comment AS c3, comments_table.file_id AS c4, comments_table.com_date AS date, IF(comments_table.comid IS NOT NULL, 'Friends_Comments', FALSE) as Type
    FROM friendship
    LEFT JOIN user_table ON friendship.userid = user_table.userid
    LEFT JOIN comments_table ON user_table.userid = comments_table.userid
    WHERE friendship.friendid = $userid
    AND friendship.STATUS = '1'
UNION
-- Find comments of friendship.userid=$userid
SELECT comments_table.comid AS c1, user_table.username AS c2, comments_table.dl_comment AS c3, comments_table.file_id AS c4, comments_table.com_date AS date, IF(comments_table.comid IS NOT NULL, 'Friends_Comments', FALSE) as Type
    FROM friendship
    LEFT JOIN user_table ON friendship.friendid = user_table.userid
    LEFT JOIN comments_table ON user_table.userid = comments_table.userid
    WHERE friendship.userid = $userid
    AND friendship.STATUS = '1'
-- Last comments on member's files
UNION ALL
SELECT comments_table.comid AS c1,user_table.username AS c2,comments_table.dl_comment AS c3, files_table.file_id AS c4,comments_table.com_date AS date, IF(comments_table.comid IS NOT NULL, 'My_Comments', FALSE) as Type
FROM files_table
LEFT JOIN comments_table ON files_table.file_id = comments_table.file_id
LEFT JOIN user_table ON comments_table.userid = user_table.userid
WHERE
(files_table.status=1) AND
(files_table.dlauthor=$userid)
ORDER by date DESC

解释:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     friendship  ref     friendid    friendid    3   const   22  Using where
1   PRIMARY     user_table  eq_ref  PRIMARY     PRIMARY     4   ketabnak_ebooks.friendship.userid   1    
1   PRIMARY     files_table     ref     dlauthor    dlauthor    92  func    10   
2   UNION   friendship  ref     PRIMARY     PRIMARY     3   const   11  Using where
2   UNION   user_table  const   PRIMARY     PRIMARY     4   const   1    
2   UNION   files_table     ref     dlauthor    dlauthor    92  func    10   
3   UNION   friendship  ref     friendid    friendid    3   const   22  Using where
3   UNION   user_table  eq_ref  PRIMARY     PRIMARY     4   ketabnak_ebooks.friendship.userid   1    
3   UNION   comments_table  ref     userid  userid  3   ketabnak_ebooks.user_table.userid   6    
4   UNION   friendship  ref     PRIMARY     PRIMARY     3   const   11  Using where
4   UNION   user_table  eq_ref  PRIMARY     PRIMARY     4   ketabnak_ebooks.friendship.friendid     1    
4   UNION   comments_table  ref     userid  userid  3   ketabnak_ebooks.user_table.userid   6    
5   UNION   files_table     ref     dlauthor    dlauthor    92  const   294     Using where
5   UNION   comments_table  ref     file_id     file_id     3   ketabnak_ebooks.files_table.file_id     11   
5   UNION   user_table  eq_ref  PRIMARY     PRIMARY     4   ketabnak_ebooks.comments_table.userid   1    
NULL    UNION RESULT    <union1,2,3,4,5>    ALL     NULL    NULL    NULL    NULL    NULL    Using filesort

弱点:

  • 查询花费了很多时间。

  • 所有表的列数应该相等。


我已经使用Friendship 表找到所有会员的朋友。 Status当会员的好友被接受好友请求时为1。

首先,Userid = Memberid:

Userid   | Friendid    | Status
1        |      4      |     0
1        |      8      |     1
1        |      9      |     1

然后,我使用 UNION 来合并 where Friendid = Memberid:

Userid   | Friendid    | Status
2        |      1      |     0
3        |      1      |     0
5        |      1      |     1

【问题讨论】:

  • 能否请您发布您联合的每个查询的执行计划?我想friendship 表比其他表要少得多,在这种情况下,最好先过滤掉这个表,然后将它与查询中的其余表连接起来
  • 如你所见,我不擅长 MySQL。我的查询可以正常工作,但我很确定它会好得多。我不知道如何使用Friendship 表作为过滤器。你能帮忙吗?
  • 要添加计划,请执行“explain put_your_query_here”并将其添加到您的帖子中。请尝试以下查询 link 并将其与您在 union 中的第一个查询进行比较。
  • 解释我的查询:pastebin.com/BFz2G1dU 解释你的查询:pastebin.com/4qw89bEZ
  • 计划似乎没问题。请确保您在friendship.friendid 上有索引。这就是我能帮助你的全部。我想还有另一种改进方法(但我可以帮助或不能......这取决于......):您可以重写您的查询并从联合中的每个查询中选择user_table 并将此表与结果集连接起来。这就是我所能建议的。

标签: mysql sql facebook union facebook-wall


【解决方案1】:

让它变得更好的一个想法是不要再认为你必须在一个查询中完成所有事情。

【讨论】:

    【解决方案2】:

    可能有人有更好的主意,当然,总有人比你聪明,反正我想分享这个方法,这是我在 1 年前做的并且为我工作的东西,这是为 symfony 1.4 做的, symfony 1.4 不用知道,一目了然。

    公共函数 getAllEvents($uid) { $result = Doctrine_Query::create()->from('AquilaWall w')->where('w.uid = ? && w.is_public=1 ', $uid)->execute(); $array_uids = 数组(); foreach ($result 为 $uid_record){ array_push($array_uids, $uid_record->getUid()); array_push($array_uids, $uid_record->getUids()); } $array_uids = array_unique($array_uids); $array_uids = array_filter($array_uids); $array_uids = implode(",",$array_uids); $mdarray=数组(); $标志=0; $rowcount= $result -> count(); 如果 ($rowcount>0) { // 初始化数组 $arr_wall_videos = $arr_wall_cmets = $arr_wall_news = $arr_wall_faqs =array(); $num_videos = $this->getNumberOf("AquilaVideos", $uid); 如果($num_videos>0){ $query = "SELECT * FROM aquila_videos WHERE uid IN ($array_uids)"; $arr_wall_videos = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchAssoc($query); $标志=1; } $num_news = $this->getNumberOf("AquilaNews", $uid); 如果($num_news>0){ $query = "SELECT * FROM aquila_news WHERE uid IN ($array_uids)"; $arr_wall_news = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchAssoc($query); $标志=1; } $num_faqs = $this->getNumberOf("sfFaqFaq", $uid); 如果($num_faqs>0){ $query = "SELECT faq.uid, faq.id, faq.created_at, faq.question, faq.slug, cat.name FROM sf_faq_faq faq INNER JOIN sf_faq_category cat on cat.id=faq.category_id WHERE faq.uid IN ($ array_uids)"; $arr_wall_faqs = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchAssoc($query); $标志=1; } $num_cmets = $this->getNumberOf("评论", $uid); 如果 ($num_cmets>0) { $query = "SELECT * FROM comment WHERE user_id IN ($array_uids)"; $arr_wall_cmets = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchAssoc($query); $标志=1; } 如果($标志){ $mdarray = array_merge((array)$arr_wall_videos, (array)$arr_wall_faqs); $mdarray = array_merge((array)$mdarray, (array)$arr_wall_news); $mdarray = array_merge((array)$mdarray, (array)$arr_wall_cmets); foreach ($mdarray as $key => $row) { $dates[$key] = $row['created_at']; } array_multisort($dates, SORT_DESC, $mdarray); } } 返回 $mdarray; }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多