我有三个表: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表。一种方法(更快,更有效)比另一种更好吗?
答案 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