Mysql联合在同一组表上


Mysql Unions on the Same Set of Joined Tables

如果这个问题以前出现过,我很抱歉,但我找不到一个可靠的答案。

我正试图从我的表中与另一个表连接的一组3列中获得一列id。

获取单列的select语句如下:

SELECT id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue = X;

根据我的理解,我可以使用并集来得到这样的结果:

SELECT spec_id1 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue1 = X
UNION
SELECT spec_id2 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue2 = Y
UNION
SELECT spec_id3 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue3 = Z

是否有一种方法来重用TableA JOIN TableB USING (key1, key2),所以它不是为每个选择连接?我还有一个WHERE条件,适用于上面没有显示的所有选择。我是否可以重复使用如下代码:

FROM TableA JOIN TableB USING (key1, key2) WHERE someOtherValue = W

我正在尝试使用mysqli在PHP中做到这一点。我最初的直觉是使用临时表并查询它,但我不确定如何在mysqli中处理它。如果我可以将表用于以下多个查询,那么这将是双重理想的,因为在连接的表中有可以稍后使用的额外数据。

抱歉,如果这是天真的,但我不是一个真正的大型web开发人员。提前谢谢。

编辑:我正在寻找临时表,似乎这可能是一个很好的方法。在做任何事情之前,我还是想确认一下这是不是一个好主意。

没有捷径——除非改变表的设计。你的方法是可靠的,你不应该担心在你的查询中有3个连接。

如果已知3个spec_id列表没有任何重叠的值,那么您可以通过将UNION更改为UNION ALL来提高性能。


一个可能的重写,不改变整体的UNION计划,是改变连接到EXISTS子查询:

    SELECT spec_id1 AS id 
    FROM TableA 
    WHERE EXISTS
          ( SELECT * 
            FROM TableB 
            WHERE (TableB.key1, TableB.key2) = (TableA.key1, TableA.key2)
              AND someValue1 = X
          )
UNION                --- or UNION ALL
    ...
UNION
    ...

或者-如果spec_ids都包含在另一个BaseTable中-你可以有这样的东西,这可能会产生更好的执行计划:

SELECT id
FROM BaseTable
WHERE EXISTS
      ( SELECT * AS id 
        FROM TableA 
          JOIN TableB 
            USING (key1, key2) 
        WHERE someValue1
          AND TableA.spec_id1 = BaseTable.id
      )
    OR EXISTS
       ( 
       ...
       )
    OR ...

Try CASE语句。不需要UNION

也可以这样做
SELECT 
    CASE 
        WHEN someValue1 = X THEN spec_id1 
        WHEN someValue2 = Y THEN spec_id2 
        WHEN someValue3 = Z THEN spec_id3 
    END
 AS id FROM TableA JOIN TableB USING (key1, key2) 
WHERE 
someValue1 = X OR someValue2 = Y OR WHERE someValue3 = Z