加入哪里的条件

时间:2011-04-06 10:04:37

标签: mysql join

我在这里阅读了许多加入问题,但无法理解并创建自己的问题以获得我想要的正确结果。

我现在有三个表状态成员好友好友表有两列friend_id和member_id

  1. 所有三个表都具有member_id公共主要成员表id
  2. 现在我希望获得会员和会员朋友创建的所有状态
  3. 如果我有三名成员,身份证号为1,2,3
  4. 朋友表有id的1,2,所以这两个成为彼此的朋友
  5. 2有5个状态更新,1个有2个状态,3个状态表中有1个更新
  6. 如果我查询会员2,它应该返回7条记录...(5表示2,2表示1),不应该返回成员3的记录。
  7. 如果我查询成员1,它应该返回与第5点相同的记录。
  8. 我需要更改表格结构吗?请帮助如何以我想要的方式获取记录

    three tables structure attached

3 个答案:

答案 0 :(得分:1)

对于任何合格成员的预先查询对于任何合格成员加上成员本身,然后返回加入其余表格...

select STRAIGHT_JOIN 
      PeopleList.Member_id,
      members.last_name,
      members.first_name,  (etc with any other fields)
      ms.status_id,
      ms.description (etc with any other fields from member_status table)
   from
      ( Select DISTINCT m.member_id
            from Members m
            where m.member_id = MemberDesiredVariable
        union select f.friend_id AS member_id
            from Friends f
            where f.member_id = MemberDesiredVariable
        union select f2.member_id
            from Friends f2
            where f2.friend_id = MemberDesiredVariable ) PeopleList
      join members
         on PeopleList.member_id = members.member_id
      join member_status ms
         on PeopleList.member_id = ms.member_id

无论在“朋友”表中是否有任何记录的人,这都应该是主要人物,例如没有条目的新人......他们至少有资格成为自己并加入成员和member_status表。

然后,在你的方案中,成员1是标准,它会查询朋友的任何“Friend_IDs”,因此DISTINCT将有1(直接来自成员)和2,其中member_id = 1,找到Friend_id = 2.现在,这个预查询有两个ID,然后继续获取你想要的其他任何细节。

第三种情况是你想要成员2 ...所以,直接查询成员表保证他们在列表中的ID要处理,但由于他们的ID不是朋友表中的“MEMBER_ID”,它必须从别人那里寻找自己的“FRIEND_ID”并抓住会员的身份证。所以现在,成员2也将找到成员1并继续获取详细信息。

对于成员3,如果你查询了Friends表,你根本就没有记录,即使成员3有一些状态记录......它必须是自己的资格以包含其余的处理......但在朋友表中不会发现自己是“member_id”或“friend_id”。

我实际上无法在我当前的位置对此进行测试,但逻辑上应该没问题。

最后,如果您希望朋友名称REGARDLESS更改“状态”,请将最后一次加入更改为member_status为LEFT JOIN。

---评论反馈

我不能特别推荐任何书籍,它只是来自多年的经验...... 1.了解您的数据的关系...
2.找出最内在的“我想得到什么” 3.抛出所有其他元素,直到获得CRITERIA,而不是内容。 4.保持你的主要“获得标准”...然后加入你的其他表。 5.然后在输出结果集

中添加所需的所有其他字段

尝试解决复杂查询通常会被人们试图获取的所有其他数据元素混乱。像许多其他编程任务一样...我喜欢让它工作,然后使它漂亮。查询也是如此。如果您的基线查询没有得到您想要的内容,那么您连接在一起的多少个其他表(左,外或正常连接)无关紧要,您的输出将是错误的。

我还在顶部的sql中添加了“STRAIGHT_JOIN”子句。这告诉MySql按照我指示的顺序执行查询,并且没有优化器尝试为我考虑。当连接主表(例如数百万条记录)以“查找”辅助表时,这一个子句经常出现,查询引擎错误地将查找表解释为查询表的主要查询表,从而导致性能下降......

尝试在有效的版本之间进行一些定时测试。如果它们具有相同的可比性,我通常会使用我能理解的那个,以防我将来必须修改/更改某些内容。

答案 1 :(得分:0)

-- own records
SELECT member_id, friend_id, user_name, description
FROM
(SELECT M.member_id,
        M.member_id friend_id,
        M.user_name,
        MS.description
   FROM members M
   LEFT JOIN member_status MS on MS.member_id = M.member_id
UNION ALL
-- friends records
SELECT M.member_id,
       F.friend_id,
       MF.user_name,
       MS.description
  FROM members M
  JOIN (      SELECT friend_id member_id, member_id friend_id from friends 
        UNION SELECT member_id, friend_id from friends) F
                              ON F.member_id = M.member_id 
  LEFT JOIN member_status MS on MS.member_id = F.friend_id
  LEFT JOIN members MF       on MF.member_id = F.friend_id) R
WHERE R.member_id = 1

答案 2 :(得分:0)

以下是使用UNION子句的解决方案。如果每个SELECT的结果很短(假设少于1000行),那么它比LEFT JOIN与OR结合更快。

如果是“彼此的朋友”,那么你的意思是: (a)被标记为朋友的成员的身份 +
(b)被视为成员被标记为朋友的成员的地位 那么你应该使用下面的树UNION 如果只想要(a),则删除最后一个UNION。

SELECT s.status_id
 FROM member_status AS s
 WHERE (s.member_id=@id)

UNION ALL

SELECT s.status_id
 FROM member_status AS s
 INNER JOIN friends AS f ON (s.member_id=f.friend_id)
 WHERE (f.member_id=@id)

UNION ALL

SELECT s.status_id
 FROM member_status AS s
 INNER JOIN friends AS f ON (s.member_id=f.member_id)
 WHERE (f.friend_id=@id)