暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SQL 不用 UNION 操作符实现 UNION 的效果

SQL实现 2021-04-29
1876

当我们要合并两个表或者多个表的结果时,可使用 UNION ALL
或者 UNION
操作符, UNION
 和 UNION ALL
的区别在于前者会对结果集去重,而后者不会。

今天我们要解决的问题是:如果不用 UNION
 和UNION ALL
操作符,怎么实现和它们一样的效果?

假如有两个表:a 和 b,它们都只有两个字段 id 和 v,表中的数据如下:

WITH a AS(
SELECT 1 AS id,'aaa' AS v
UNION ALL
SELECT 2 AS id,'bbb' AS v
UNION ALL
SELECT 2 AS id,'bbb' AS v
),b AS (
SELECT 1 AS id,'aaa' AS v
UNION ALL
SELECT 3 AS id,'ccc' AS v
)

a 表的数据的特点是存在两条一样的记录(2,'bbb'),b 表的数据没有重复,a 表和 b 表存在相同的记录(1,'aaa')。

SELECT * FROM a UNION ALL SELECT * FROM b
的结果是:

    id  v
------ --------
1 aaa
2 bbb
2 bbb
1 aaa
3 ccc

SELECT * FROM a UNION SELECT * FROM b
的结果是:

    id  v
------ --------
1 aaa
2 bbb
3 ccc

假设在结果集里已经存在 a 表的数据,现在要把 b 表的数据也加进来,是不是可以用 LEFT JOIN
呢?

试试 SELECT * FROM a LEFT JOIN b ON b.id = a.id
的效果。

    id  v           id  v
------ ------ ------ --------
1 aaa 1 aaa
2 bbb (NULL) (NULL)
2 bbb (NULL) (NULL)

这结果看着不太行。如果我们再引入另外一张表 c,用 c 分别去关联 a 表跟 b 表,那会是什么样的结果?

c 表只有一个字段 flag,表中有两行记录:

c AS (
SELECT 0 AS flag
UNION ALL
SELECT 1 AS flag
)

引入 c 表后, SQL 可以这么写:

SELECT * FROM c
LEFT JOIN
a ON c.flag = 0
LEFT JOIN
b ON c.flag = 1

这段 SQL 的运行结果:

  flag      id  v           id  v
------ ------ ------ ------ --------
0 2 bbb (NULL) (NULL)
0 2 bbb (NULL) (NULL)
0 1 aaa (NULL) (NULL)
1 (NULL) (NULL) 3 ccc
1 (NULL) (NULL) 1 aaa

仔细看这个结果,离我们要实现的 UNION ALL
的结果有点近了,我们把相同的字段的值合并到一块就能达到 UNION ALL
的效果了。

合并两个字段的值可以用函数 COALESCE()
,COALESCE()
函数可以传入多个参数,并返回第一个非 NULL
的值。

完整的 SQL 如下:

SELECT
COALESCE(a.id, b.id) AS id,
COALESCE(a.v, b.v) AS v
FROM
c
LEFT JOIN a
ON c.flag = 0
LEFT JOIN b
ON c.flag = 1

要实现 UNION
的效果,只需在 SELECT
子句里加入 DISTINCT
关键字即可。

SELECT DISTINCT
COALESCE(a.id, b.id) AS id,
COALESCE(a.v, b.v) AS v
FROM
c
LEFT JOIN a
ON c.flag = 0
LEFT JOIN b
ON c.flag = 1


最后修改时间:2021-04-29 23:14:51
文章转载自SQL实现,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论