【问题标题】:mysql cross join not in?mysql cross join 不进去?
【发布时间】:2010-12-09 20:16:31
【问题描述】:

使用如下查询,您可以获取 id 的颜色为蓝色、紫色、绿色、白色和黑色的行。

SELECT t1.id, col
FROM extra as e INNER JOIN your_table as t1 USING ( id )
CROSS JOIN your_table as t2 USING ( id )
CROSS JOIN your_table as t3 USING ( id )
CROSS JOIN your_table as t4 USING ( id )
CROSS JOIN your_table as t5 USING ( id )
WHERE t1.color = 'blue' and t2.color = 'purple' and t3.color= 'green' and t4.color= 'white' and t5.color= 'black'

如果您尝试使用 != 或 NOT IN,它似乎不起作用。我将如何编写查询以使颜色包含蓝色、紫色、绿色、白色,但不包含黑色?

【问题讨论】:

    标签: mysql sql sql-match-all


    【解决方案1】:

    你可以按照以下方式做一些事情:

    select e.id
    from   extra as e
    where  exists (select null from your_table as t where t.id = e.id and t.color = 'blue')
      and  exists (select null from your_table as t where t.id = e.id and t.color = 'purple')
      and  exists (select null from your_table as t where t.id = e.id and t.color = 'green')
      and  exists (select null from your_table as t where t.id = e.id and t.color = 'white')
      and not exists (select null from your_table as t where t.id = e.id and t.color = 'black')
    

    或者,这样的事情可能会更有效:

    select e.id
    from   extra as e
    where  4 = 
           (select count(*) 
            from   your_table as t 
            where  t.id = e.id 
              and  t.color in ('blue', 'purple', 'green', 'white'))
      and  0 = 
           (select count(*) 
            from   your_table as t 
            where  t.id = e.id 
              and  t.color in ('black'))
    

    【讨论】:

    • 是的,这行得通,但令人惊讶的是,第一个实际上更有效。它比第二次查询快大约 2-3 倍。但是,我原来的交叉连接大约是第一个交叉连接的两倍。这是选择不存在的东西的成本吗?
    • 如果您没有索引,您可以尝试在 (id, color) 上为your_table 添加索引。
    • 啊,是的,我认为这就是问题所在。 id 被索引,但不是第二列。现在快多了。两个查询的速度似乎差不多,但第 2 个查询的“依赖子查询”较少,所以我认为这样会更好。
    【解决方案2】:

    我不知道你为什么使用CROSS JOIN。这通常用于生成笛卡尔积。您只需要一个简单的INNER JOIN 或简单的JOIN

    当我想测试是否缺少某些数据时,我通常使用OUTER JOIN。找不到匹配项时,t5 将为 NULL。

    SELECT t1.id, col
    FROM extra as e 
    INNER JOIN your_table as t1 ON ( e.id=t1.id AND t1.color = 'blue' )
    INNER JOIN your_table as t2 ON ( e.id=t2.id AND t2.color = 'purple' )
    INNER JOIN your_table as t3 ON ( e.id=t3.id AND t3.color = 'green' )
    INNER JOIN your_table as t4 ON ( e.id=t4.id AND t4.color = 'white' )
    LEFT OUTER JOIN your_table as t5 ON ( e.id=t5.id AND t5.color = 'black' )
    WHERE t5.id IS NULL;
    

    您是对的,上述使用连接的技术比使用相关子查询更快,而且(至少在 MySQL 中)它也比某些人使用的 GROUP BY 解决方案更快:

    SELECT e.id, col
    FROM extra as e
    INNER JOIN your_table AS t USING ( id)
    WHERE t.color IN ('blue', 'purple', 'green', 'white')
    GROUP BY e.id
    HAVING COUNT(*) = 4;
    

    (这个查询并没有解决“不是黑色”的问题,我只是在说明技术。)

    【讨论】:

    • cross joininner join 在 MySQL 中是同义词(但在 ANSI SQL 中不是)。 +1 left outer join 的好主意。
    • 酷,感谢您启发和分享另一种有效的方法。
    【解决方案3】:

    我认为您使查询过于复杂,您尝试的似乎是这样的标准联接

    select * from cars join colors where cars.colorid = colors.colorid where colors.color != 'black'
    

    【讨论】:

    • 我假设第二个 AND 在哪里?但是,是的,这是行不通的。
    猜你喜欢
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 2014-06-23
    • 2013-07-19
    • 2011-07-03
    • 1970-01-01
    相关资源
    最近更新 更多