【问题标题】:join with where condition加入 where 条件
【发布时间】:2011-04-07 08:17:43
【问题描述】:

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

我现在有三个表,分别是 statusmembersfriends 朋友表有两列friend_id 和 member_id

  1. 所有三个表都有 member_id 成员表的公共主 id
  2. 现在我想获取会员和会员朋友创建的所有状态
  3. 如果我有三个成员的 id 为 1,2,3
  4. friends 表的 id 为 1,2,因此这两个成为彼此的朋友
  5. 在状态表中有 5 个状态更新,1 个有 2 个状态,3 个有 1 个更新
  6. 如果我查询成员 2,它应该返回 7 条记录...(5 代表 2,2 代表 1)并且不应该返回成员 3 的记录。
  7. 如果我查询成员 1,它应该返回与第 5 点相同的记录。

我需要改变我的表格结构吗?请帮助如何以我想要的方式获取记录

【问题讨论】:

  • 当你说“friends table has id's 1,2”是两行,还是只有一行member_id=1和friend_id=2?
  • @Skrol29 只有一行 member_id=1 和friend_id=2

标签: mysql join


【解决方案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_ID”,因此 DISTINCT 将具有 1(直接来自成员)和 member_id = 1 的 2,找到Friend_id = 2。所以现在,这个预查询有两个 ID,然后继续获取您想要的任何其他详细信息。

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

对于成员 3,如果您针对 Friends 表进行查询,则根本不会得到任何记录,即使成员 3 有一些状态记录......它必须对自己进行限定才能包含其余的处理中...但在朋友表中不会发现自己是“member_id”或“friend_id”。

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

最后,如果您希望好友名称不考虑任何“状态”更改,请将上次加入 member_status 更改为 LEFT JOIN。

--- 评论反馈

我不能具体推荐任何书籍,它只是来自多年的经验...... 1. 了解您的数据之间的关系...
2. 找出内心深处的“我想得到什么”。
3. 排除所有其他元素,直到获得 CRITERIA,而不是 CONTENT。 4. 将您的主要“获取标准”放在前面……然后加入您的其他表格。 5.然后在输出结果集中添加你想要的所有其他字段

试图解决复杂的查询通常会被人们试图获取的所有其他数据元素所困扰。像许多其他编程任务一样......我喜欢让它工作,然后让它变得漂亮。查询也是如此。如果您的基线查询没有得到您想要的结果,那么无论您连接多少其他表(左连接、外连接或普通连接),您的输出都将是错误的。

我还在顶部的 sql 中添加了子句“STRAIGHT_JOIN”。这告诉 MySql 按照我指示的顺序进行查询,并且不要让优化器尝试为我考虑。在将主表(例如数百万条记录)连接到“查找”辅助表时,这一子句出现得如此频繁,以至于查询引擎错误地将查找表解释为查询的主表,从而扼杀了性能......

尝试在可用的版本之间进行一些定时测试。如果它们具有同等的可比性,我通常会选择我能理解的那个,以防我将来不得不修改/更改某些东西。

【讨论】:

  • 非常感谢 DRapp,它工作得很好 :) 你在没有测试的情况下编写它,你能推荐任何关于 sql 的书或教程,我可以提高我的 sql 技能...... Manji 查询也有效我有不知道哪个更好,但您的查询看起来更干净......
  • 没问题,我已经用其他查询说明/调整更新了答案。
【解决方案2】:
-- 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

【讨论】:

  • Manji 非常感谢你,它只需要很少的添加或声明就可以工作......在friends.member_id = members.member_id 或friends.friend_id = members.member_id 上加入朋友...你能不能描述整个查询?详细:)
  • 如果会员没有朋友,那么即使会员有状态,这个查询也不返回任何记录。
  • Hi Manji....得到了 1 个问题查询,返回成员 ID 1,2 的相同名字和第二个名称,但返回成员 1 和 2 的记录,可以在哪里进行更改,所以它首先返回不同,第二个名字?
  • @Manji 你能解决这个问题吗?
  • 你能测试一下新的查询吗?最好分别为会员和朋友获取记录。
【解决方案3】:

这是使用 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)

【讨论】:

    猜你喜欢
    • 2014-03-29
    • 2016-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    • 2018-02-25
    • 1970-01-01
    相关资源
    最近更新 更多