SQL-UNION与NULL函数。哪个更好?

时间:2019-01-03 21:30:55

标签: sql oracle

我有三个表: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    |
+---------+--------------+---------------+----------+-------+

ORG表:

+--------+--------------+--------------+----------+-------+
| 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表。一种方法(更快,更有效)比另一种更好吗?

2 个答案:

答案 0 :(得分:2)

这取决于您认为“更好”的情况。

假设您将始终要从ACCT表中提取所有行,那么我想选择LEFT OUTER JOIN而不选择UNION。 (如果使用UNION,则应使用UNION ALL变体。)

编辑:由于您已经显示了查询,因此不再需要我的查询,并且与您的结构不匹配。删除此部分。

为什么LEFT JOIN?因为对于UNION,您必须根据“父级”标准(无论是单独的还是完成ACCT的标准)经历两次INNER JOIN,而对于普通的LEFT OUTER JOIN,您必须我只能通过ACCT一遍。在这两种情况下,最有可能基于主键访问“父级”中的行。

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

答案 1 :(得分:0)

我认为您误解了Union而不是join语句。联合会从通常具有相似或相同结构的多个表中获取记录,并将它们组合为一个结果集。这并不意味着要合并多个不同的表。

我看到的是您有两个表PERS和ORG,其中包含一些相同的数据。在这种情况下,我建议您合并这两个表,然后加入ACCT以获取示例输出。

在这种情况下,如您所显示的那样获得输出,您将要使用外部联接,这样就不会删除没有匹配项的任何记录。那会在某些地方为您提供空值,但是大多数时候这就是您想要的。以后将它们过滤掉要容易得多。

非常粗糙的示例代码。

SELECT a.*, b.* 
from Acct as a
FULL OUTER JOIN ( 
   Select * from PERS UNION Select * from ORG
      ) as b
ON a.ID = b.ID