同一组连接表上的 Mysql 联合
Posted
技术标签:
【中文标题】同一组连接表上的 Mysql 联合【英文标题】:Mysql Unions on the Same Set of Joined Tables 【发布时间】:2012-01-14 10:10:39 【问题描述】:因此,如果以前出现过这种情况,我深表歉意,但我找不到可靠的答案。
我正在尝试从与另一个表连接的表中的一组 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 中处理它。如果我可以将该表用于多个以下查询,那将是双重理想的,因为连接表中有额外的数据可以稍后使用。
对不起,如果这太天真了,但我并不是一个真正的大型网络开发人员。提前致谢。
编辑: 我正在研究临时表,这似乎是解决它的好方法。在对它进行任何操作之前,我仍然希望确认这是否是一个好主意。
【问题讨论】:
您可以尝试CASE
声明:dev.mysql.com/doc/refman/5.0/en/… 虽然我不太确定这对您的情况有多大用处。我知道您要做什么,但是,一旦将这些列组合在一起,您将如何判断哪个值来自哪个列?
我不在乎它来自哪个专栏。给你一个更具体的例子来说明我在做什么,这 3 列类似于经理 ID、协调员 ID 和主管 ID。每个角色都是截然不同的角色,尽管看起来可能并不像。我正在努力向他们发送一封类似的电子邮件,这只是一般管理类型的电子邮件。无论他们的确切位置如何,他们都会收到相同的电子邮件,因此尽管出于其他原因需要 3 个不同的列,但他们都会收到相同的电子邮件。
啊,明白了。是的,我建议使用 CASE
语句和组合 WHERE
子句,然后如果你真的决定只执行一个查询。
【参考方案1】:
没有捷径可走——除非改变表格的设计。您的方法很可靠,您不必担心查询中有 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 ...
【讨论】:
如果 3 个列表中的每个列表中可能存在重叠值,但 3 个列表之间没有重叠值,使用 UNION ALL 执行 SELECT DISTINCT 或使用 UNION 执行 SELECT(没有不同或全部)会更便宜吗? 我猜是第一个但最好的方法是测试它(使用您的数据)。如果可以使用UNION ALL
,则应该尝试分别优化3个子查询。
确实如此 :-p 出于某种原因,我总是尝试优化然后尝试。我不习惯大多数东西都可以立即测试的 Web 开发。 ;)【参考方案2】:
试试 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
【讨论】:
以上是关于同一组连接表上的 Mysql 联合的主要内容,如果未能解决你的问题,请参考以下文章