首页 > 解决方案 > SQL - UNION 与 NULL 函数。哪个更好?

问题描述

我有三个表:ACCT、PERS、ORG。每个 ACCT 由 PERS 或 ORG 拥有。PERS 和 ORG 表非常相似,它们的所有子表也是如此,但所有 PERS 和 ORG 数据都是独立的。

我正在编写一个查询来获取 ACCT 中每个帐户的 PERS 和 ORG 信息,我很好奇组合这些信息的最佳方法是什么。我应该使用一系列左连接和 NULL 函数来填补空白,还是应该单独编写查询并使用 UNION 组合?

我已经为 PERS ACCT 编写了单独的查询,为 ORG ACCT 编写了另一个查询,并计划使用 UNION。我的问题更多地与未来的最佳实践有关。

我希望两者都能给我想要的结果,但我想在开发时间和运行时间都找到最有效的方法。

编辑:样本表数据

ACCT表:

+---------+---------+--------------+-------------+
| ACCTNBR | ACCTTYP | OWNERPERSNBR | OWNERORGNBR |
+---------+---------+--------------+-------------+
|  555001 | abc     |         3010 |             |
|  555002 | abc     |              |        2255 |
|  555003 | tre     |         5125 |             |
|  555004 | tre     |         4485 |             |
|  555005 | dsa     |              |        6785 |
+---------+---------+--------------+-------------+

PERS 表:

+---------+--------------+---------------+----------+-------+
| PERSNBR |    PHONE     |    STREET     |   CITY   | STATE |
+---------+--------------+---------------+----------+-------+
|    3010 | 555-555-5555 | 1234 Main St  | New York | NY    |
|    5125 | 555-555-5555 | 1234 State St | New York | NY    |
|    4485 | 555-555-5555 | 6542 Vine St  | New York | NY    |
+---------+--------------+---------------+----------+-------+

组织表:

+--------+--------------+--------------+----------+-------+
| ORGNBR |    PHONE     |    STREET    |   CITY   | STATE |
+--------+--------------+--------------+----------+-------+
|   2255 | 222-222-2222 | 1000 Main St | New York | NY    |
|   6785 | 333-333-3333 | 400 4th St   | New York | NY    |
+--------+--------------+--------------+----------+-------+

期望的输出:

+---------+---------+--------------+-------------+--------------+---------------+----------+-------+
| ACCTNBR | ACCTTYP | OWNERPERSNBR | OWNERORGNBR |    PHONE     |    STREET     |   CITY   | STATE |
+---------+---------+--------------+-------------+--------------+---------------+----------+-------+
|  555001 | abc     |         3010 |             | 555-555-5555 | 1234 Main St  | New York | NY    |
|  555002 | abc     |              |        2255 | 222-222-2222 | 1000 Main St  | New York | NY    |
|  555003 | tre     |         5125 |             | 555-555-5555 | 1234 State St | New York | NY    |
|  555004 | tre     |         4485 |             | 555-555-5555 | 6542 Vine St  | New York | NY    |
|  555005 | dsa     |              |        6785 | 333-333-3333 | 400 4th St    | New York | NY    |
+---------+---------+--------------+-------------+--------------+---------------+----------+-------+

查询选项 1:编写 2 个查询并使用 UNION 将它们组合起来:

select a.acctnbr, a.accttyp, a.ownerpersnbr, a.ownerorgnbr, p.phone, p.street, p.city, p.state
from acct a 
inner join pers p on p.persnbr = a.ownerpersnbr

UNION

select a.acctnbr, a.accttyp, a.ownerpersnbr, a.ownerorgnbr, o.phone, o.street, o.city, o.state
from acct a
inner join org o on o.orgnbr = a.ownerorgnbr 

选项 2:使用 NVL() 或 Coalesce 返回单个数据集:

SELECT a.acctnbr,
a.accttyp,
NVL(a.ownerpersnbr, a.ownerorgnbr) Owner,
NVL(p.phone, o.phone) Phone,
NVL(p.street, o.street) Street,
NVL(p.city, o.city) City,
NVL(p.state, o.state) State

FROM
acct a
LEFT JOIN pers p on p.persnbr = a.ownerpersnbr
LEFT JOIN org o on o.orgnbr = a.ownerorgnbr

在我的实际查询中,这 3 个表中的每一个都有更多的字段以及更多的 PERS 和 ORG 表。一种方法比另一种更好(更快,更有效)吗?

标签: sqloracle

解决方案


这取决于您认为“更好”的内容。

假设您总是想从ACCT表中提取所有行,我会说选择LEFT OUTER JOINand no UNION。(如果使用UNION,那么宁愿选择UNION ALL变体。)

编辑:正如您已经展示了您的查询,我的不再需要,并且与您的结构不匹配。删除这部分。

为什么LEFT JOIN?因为UNION你必须通过ACCT两次,基于“父”标准(无论是单独的还是完成的INNER JOIN标准),而使用plain LEFT OUTER JOIN,你可能只会通过一次ACCT。在这两种情况下,来自“父母”的行很可能会根据主键来访问。

由于您可能正在考虑性能,因此在寻找“更好”时,一如既往:测试您的查询并查看执行计划,并根据数据“布局”(直方图等)提供足够和新鲜的数据库统计信息“更好”可能是完全不同的东西。


推荐阅读