mysql - 可以以某种方式将 UNION 转换为 JOIN 吗?
问题描述
这是一个有点奇怪的问题,但我想知道,如果使用两个结构相同的表,可以进行连接以模拟常见的联合查询,例如:
SELECT * FROM table1
UNION
SELECT * FROM table2
我唯一的(黑客)想法是有一个“NULL行”table1
并将该值交叉连接到表2,然后对table2中的每个值使用COALESCE来“覆盖”table1中的那个......我知道正确的方法要做到这一点是与一个联合,但这只是我想知道是否有可能将一个联合转换为一个连接。
解决方案
这不能在 MySQL 中完成,但如果您使用的 SQL 版本支持FULL OUTER JOIN
,则可以使用始终为假的JOIN
条件来模拟UNION
例如
SELECT COALESCE(t1.a, t2.a) AS a,
COALESCE(t1.b, t2.b) AS b
FROM table1 t1
FULL OUTER JOIN table2 t2 ON 0 = 1
因为不支持FULL OUTER JOIN
,所以在 MySQL 中是做不到的,模拟的方式FULL OUTER JOIN
是用 a UNION
of aLEFT JOIN
和 a RIGHT JOIN
。
更新
使用行号,可以模拟其中任一行号为 1 的两个表中的 a,然后再次使用UNION
第二个表来复制两个行号均为 1 的行。然后一些复杂的行排序对行进行排序与以下顺序相同:JOIN
LEFT JOIN
FULL OUTER JOIN
WITH CTE1 AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY RAND()) AS rn
FROM table1
),
CTE2 AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY RAND()) AS rn
FROM table2
)
SELECT CASE WHEN c3.rn = 2 THEN CTE2.a
WHEN CTE2.rn = 1 THEN CTE1.a
ELSE CTE2.a END AS a,
CASE WHEN c3.rn = 2 THEN CTE2.b
WHEN CTE2.rn = 1 THEN CTE1.b
ELSE CTE2.b END AS b
FROM CTE1
JOIN CTE2 ON CTE1.rn = 1 OR CTE2.rn = 1
LEFT JOIN CTE2 c3 ON CTE1.rn = 1 AND CTE2.rn = 1 AND c3.rn IN (1, 2)
ORDER BY CTE2.rn,
CASE WHEN COALESCE(c3.rn, 1) = 1 THEN 0 ELSE 1 END,
CTE1.rn
注意我使用 CTE 和窗口函数(自 MySQL 8 起可用)来生成行号;在早期版本中有很多方法可以模拟行号,在这种情况下,您需要用子查询替换 CTE。
推荐阅读
- c++ - SparseLU 在 Eigen (C++) 中的计算错误
- three.js - 如何在three.js中加载带有cubemap的ktx文件?
- linux - 如何编译调用printf的nasm程序?
- c - 在 C 中使用 for 循环时,左侧操作数没有效果警告
- vba - 在更改一个单元格时,如何使用 vba 清除 Excel 表格中另一个单元格的内容。我还需要将逻辑扩展到该表中的整个列
- node.js - Mongoose 自定义虚拟字段返回承诺
- object-oriented-analysis - 结构化编程与面向对象编程
- python - Pandas 根据 Dataframe 中的所有唯一值对数据进行透视
- java - 错误的 Java 字符串连接
- bash - 是否有类似“超时”的功能可以跳过命令而不是杀死它?