2012-12-05 100 views
0

我有一个很长的查询是切换资源,并需要重写它。 它的一个显而易见的问题是在where子句中使用“not in”。 我最初的想法是重写它,废除所有的自联接,并在子查询上做一个“不存在”。有没有想过这样做,或者比这更有效的想法?一个更好的方法来写这个MySQL选择查询

这里的查询:

SELECT a.referenceid, 
     a.memberid AS d1, 
     b.memberid AS d2, 
     c.memberid AS d3, 
     d.memberid AS d4, 
     e.memberid AS d5, 
     f.memberid AS d6 
FROM jos_comprofiler_members AS a FORCE INDEX (aprm) 
     LEFT JOIN jos_comprofiler_members AS b FORCE INDEX (aprm) 
       ON a.memberid = b.referenceid 
       AND b.accepted = 1 
       AND b.pending = 0 
     LEFT JOIN jos_comprofiler_members AS c FORCE INDEX (aprm) 
       ON b.memberid = c.referenceid 
       AND c.accepted = 1 
       AND c.pending = 0 
     LEFT JOIN jos_comprofiler_members AS d FORCE INDEX (pamr) 
       ON c.memberid = d.referenceid 
       AND d.accepted = 1 
       AND d.pending = 0 
     LEFT JOIN jos_comprofiler_members AS e FORCE INDEX (pamr) 
       ON d.memberid = e.referenceid 
       AND e.accepted = 1 
       AND e.pending = 0 
     LEFT JOIN jos_comprofiler_members AS f FORCE INDEX (pamr) 
       ON e.memberid = f.referenceid 
       AND f.accepted = 1 
       AND f.pending = 0 
WHERE a.referenceid = 1593 
     AND a.accepted = 1 
     AND a.pending = 0 
     AND f.memberid = 1593 
     AND b.memberid NOT IN (1593, a.memberid) 
     AND c.memberid NOT IN (1593, a.memberid, b.memberid) 
     AND d.memberid NOT IN (1593, a.memberid, b.memberid, c.memberid) 
     AND e.memberid NOT IN (
      1593, a.memberid, b.memberid, c.memberid, d.memberid) 
     AND f.memberid NOT IN (1593, a.memberid, b.memberid, c.memberid, 
           d.memberid, e.memberid) 
LIMIT 0, 1 
+0

WOAH!这是很多... –

+0

对不起,我不清楚这些连接点是什么.. – Kermit

+0

您正试图从同一张表中获得6个不同的成员ID?你能提供关于这个查询目标的更多信息吗? – Jeffrey

回答

0

您的查询的1593反问的距离6内寻找所有成员:这个涉及到六度分离?

通常,在SQL中查找这样的列表需要递归查询或一些非SELECT构造(循环,游标)。我不知道当列表由可变成员组成时,MySQL如何处理not in。但是,我怀疑它是为每一个进行某种嵌套的循环连接。

建议:将not in声明移至on条款。例如:

LEFT JOIN jos_comprofiler_members AS c FORCE INDEX (aprm) 
      ON b.memberid = c.referenceid 
      AND c.accepted = 1 
      AND c.pending = 0 
      AND (c.memberId <> b.MemberId an c.MemberId <> a.MemberId and c.MemberId <> 1593) 

这可以改善事情。或者让它们变得更糟。但这是一个想法。

+0

感谢您的回复戈登,我终于能够确切地追踪到查询创建的位置,而您正确的,它是确定查看该配置文件的成员与配置文件拥有者之间的分离程度。我们不需要这个功能,所以暂时我只是将这个查询从函数中注释掉了。如果由于某种原因再次需要功能,它将不得不被重写,但现在看起来不可思议的哈哈。我仍然不禁想知道如何改写这种最好,最有效的方法。 –

+0

@SpencerFraise。 。 。如果您只查找一个成员,那么最好的方法可能是将该成员加载到一个临时表中,然后在while循环中一次迭代地添加成员,一次分离。 –

相关问题