在MYSQL中选择带有IN运算符的记录的最佳方法

时间:2014-11-27 06:55:32

标签: mysql sql

我有一个名为Sub_Router的表,下面有示例数据,只有两列

Associated_Router_L1,Associated_Router_L2都是复合主键。

我想为给定的L1 Routerid选择所有L2 Ronter id 例如,如果给出了2001年的结果2005,2006,2002,2007,2003,2008

我的选择sql是

查询 - 1(有一个级别)

select s1.Associated_Router_L2 
from Sub_Router s1 
where s1.Associated_Router_L1 in (select s2.Associated_Router_L2 
                                  from Sub_Router s2 
                                  where s2.Associated_Router_L1 = 2001)

查询 - 2(有两级)

select s1.Associated_Router_L2 
from Sub_Router s1 
where s1.Associated_Router_L1 in (select s2.Associated_Router_L2 
                                  from Sub_Router s2 
                                  where s2.Associated_Router_L1 in (select s3.Associated_Router_L2 
                                  from Sub_Router s3 
                                  where s3.Associated_Router_L1 = 2001))

使用内部联接的查询-2

从Sub_Router s1选择s1.Associated_Router_L2 INNER JOIN Sub_Router s2 ON s1.Associated_Router_L1 = s2.Associated_Router_L2 INNER join s_Associated_Router_L1 = s3.Associated_Router_L2上的Sub_Router s3其中s1.Associated_Router_L1 = 2001或s2.Associated_Router_L1 = 2001或s3.Associated_Router_L1 = 2001

OR操作再次创建性能

结果很好,任何更好的方法来避免这个IN,OR运算符。

表名:Sub_Router
列名:Associated_Router_L1,Associated_Router_L2两个复合主键 附加数据

Associated_Router_L1    Associated_Router_L2
                2000    2001
                2000    2002
                2000    2003
                2000    2004
                2001    2005
                2001    2006
                2001    2002
                2002    2007
                2002    2003
                2002    2008

3 个答案:

答案 0 :(得分:0)

标准SQL不擅长处理分层/树模型。

例如,Oracle已添加CONNECT BY ...以支持hierarchical queries作为非标准扩展

使用标准SQL,典型的方法是' Nested Set Model', 或者你可以使用OQGraph storage engine用于MySQL / MariaDB

答案 1 :(得分:0)

以下sql可能有所帮助:

SELECT DISTINCT concat(s2.Associated_Router_L1, '-->', s2.Associated_Router_L2) branch
FROM Sub_Router s1, Sub_Router s2
WHERE
    s1.Associated_Router_L1 = 2001
    AND (s1.Associated_Router_L2 = s2.Associated_Router_L1 OR 2001 = s2.Associated_Router_L1)

如果你想更深入一个杠杆,添加另一个表,展开WHERE子句,并修改SELECT字段:

SELECT DISTINCT concat(s3.Associated_Router_L1, '-->', s3.Associated_Router_L2) branch
FROM Sub_Router s1, Sub_Router s2, Sub_Router s3
WHERE
    s1.Associated_Router_L1 = 2001
    AND (s1.Associated_Router_L2 = s2.Associated_Router_L1 OR 2001 = s2.Associated_Router_L1)
    AND (s2.Associated_Router_L2 = s3.Associated_Router_L1 OR s1.Associated_Router_L2 = s3.Associated_Router_L1 OR 2001 = s3.Associated_Router_L1)

答案 2 :(得分:0)

可能没有任何更快,但至少可以工作到任意深度,而无需在数据或嵌套深度发生变化时重写查询。

CREATE TEMPORARY TABLE Router_List  (
    Router int)

Declare @Input_Router int
Set @Input_Router = 2001

--Prime the pump
Insert into @Router_List (Router) Values(@Input_Router)

While (1=1)
Begin

    Insert into @Router_List (Router)
    Select Associated_router_L2
    From Sub_Router SR
    Inner Join @Router_List RL
    On SR.Associated_Router_L1 = RL.Router 
    Left Join @Router_List RL2
    On SR.Associated_Router_L2 = RL2.Router
    Where RL2.Router is Null

    --Till nothing to do
    If @@ROWCOUNT = 0 Break
End

Select * from @Router_List