优化联合 sql 查询
Posted
技术标签:
【中文标题】优化联合 sql 查询【英文标题】:Optimizing a union sql query 【发布时间】:2013-05-23 00:22:32 【问题描述】:我在 3 个表之间做一个 UNION。为了让您了解情况,一张表被视为主表,另外两张表被视为子表。 2 个子表对于每种情况始终具有相同数量的记录。所以我想在这3个表之间建立一个联合,在这个联合中我想重复在主表中获取的列中的信息,并列出2个子表的信息,其中子表1中的每一行都对应于该行在子表2中。由于专业原因,我无法放置真实的代码,所以这里是一个与我的真实案例相对应的简单示例。 考虑一个名为 Author (Author_ID, Author_FirstName, Author_LastName) 的表。该表将是我们的主表。然后考虑我们有一个名为 Adresses (Adress_ID, Street_Coord, Author_ID) 的表,这将是我们的子表 1。然后考虑名为 Cities 的表 (City_ID, City_Name, Author_ID)。我们的作者 X 在 2 个城市有 2 个地址。当我执行我的查询时,我得到了完全合乎逻辑的结果 R1,但我想修改我的查询以获得结果 R2。您能帮我更改查询以获得结果 R2 吗?
SQL 查询:
SELECT "Author"."Author_ID", "Author"."Author_FirstName", "Author.Author_LastName",
TO_CHAR(NULL) AS "Street_Coord", TO_CHAR(NULL) AS "City_Name"
FROM "Author"
WHERE "Author"."Author_ID"='X'
UNION
SELECT TO_NUMBER(NULL) AS "Author_ID", TO_CHAR(NULL) AS "Author_FirstName", TO_CHAR(NULL) AS "Author_LastName",
"Adresses"."Street_Coord", TO_CHAR(NULL) AS "City_Name"
FROM "Adresses"
WHERE "Adresses"."Author_ID"='X'
UNION
SELECT TO_NUMBER(NULL) AS "Author_ID", TO_CHAR(NULL) AS "Author_FirstName", TO_CHAR(NULL) AS "Author_LastName",
TO_CHAR(NULL) AS "Street_Coord", "Cities"."City_Name"
FROM "Cities"
WHERE "Cities"."Author_ID"='X'
结果 R1:
ID_AUTHOR | AUTHOR_FirstName | AUTHOR_LastName | Street_Coord | City_Name |
----------------------------------------------------------------------------------
X |James | Conor | NULL | NULL |
----------------------------------------------------------------------------------
X |NULL | NULL | 1245 rich st | NULL |
----------------------------------------------------------------------------------
X |NULL | NULL | 154 music st | NULL |
----------------------------------------------------------------------------------
X |NULL | NULL | NULL | Madrid |
----------------------------------------------------------------------------------
X |NULL | NULL | NULL | Barcelona |
----------------------------------------------------------------------------------
结果 R2:我希望你帮助得到这个结果:
ID_AUTHOR | AUTHOR_FirstName | AUTHOR_LastName | Street_Coord | City_Name |
----------------------------------------------------------------------------------
X |James | Conor | 1245 rich st | Madrid |
----------------------------------------------------------------------------------
X |James | Conor | 154 music st | Barcelona |
----------------------------------------------------------------------------------
非常感谢, 瓦卢德
【问题讨论】:
您确定不想要 JOIN 而不是 UNION? 嘿 eaolson,11 个表的连接崩溃了! ORA-01652:无法在表空间 TEMP 01652 中将临时段扩展 128。00000 -“无法在表空间 %s 中将临时段扩展 %s” *原因:无法为临时段分配所需块数的范围在指示的表空间中。 *操作:使用 ALTER TABLESPACE ADD DATAFILE 语句将一个或多个文件添加到指定的表空间。 该错误听起来像是您需要扩展 TEMP 表空间的大小。 ***.com/questions/11839576/… 【参考方案1】:首先想到的是您真的想将这些表连接在一起。比如:
SELECT "Author"."Author_ID", "Author"."Author_FirstName", "Author.Author_LastName",
"Adresses"."Street_Coord", "Cities"."City_Name"
FROM "Author" join
"Adresses"
on Author.Author_id = Adresses.Author_id join
Cities
on Author.Author_id = Cities.Author_id
WHERE "Author"."Author_ID"='X';
但是,这将返回值的笛卡尔积,即 4 行而不是 2 行。似乎目的是“对齐”不同的表格。在这种情况下,这个查询接近你想要的:
SELECT "Author"."Author_ID", "Author"."Author_FirstName", "Author.Author_LastName",
"Adresses"."Street_Coord", "Cities"."City_Name"
FROM "Author" join
(select a.*, rownum as seqnum from "Adresses" a
) Adresses
on Author.Author_id = Adresses.Author_id join
(select c.*, rownum as seqnum from Cities c
) Cities
on Author.Author_id = Cities.Author_id and addresses.seqnum = cities.seqnum
WHERE "Author"."Author_ID"='X';
这种方法的主要问题是 SQL 表本质上是无序的。您需要一些列来对这些进行排序,以保证查询正常工作。例如,如果您在表中有一个自动递增的 id,那么每个子查询可以是 order by id
。
【讨论】:
我怀疑你的第一个答案是 Walloud 打算,但是 Cities 需要一个 address_id 而不是 author_id。 @eaolson 。 . . OP 非常清楚表格包含的内容。结构绝对不寻常。我猜它类似于具有不同列的表单上的线条。 大家好,在现实世界中我有 11 张桌子!当我在 11 个表上使用 JOIN 时,由于返回的记录数量很大,Oracle 崩溃了,这就是我使用 UNION 的原因。我只能用 UNION 找到解决方案。再次感谢! 这没有意义。这是两种不同的操作。一个 JOIN 基本上会给你额外的列,一个 UNION 会给你更多的行。这就好像你在问如何转动汽车,但你不会使用方向盘,所以你想知道如何只用油门踏板。 @Walloud。 . .我的猜测是 Oracle 崩溃是因为连接设置不正确。处理 11 个表对 Oracle 来说应该没有问题。【参考方案2】:你不想做一个 UNION,你想做一个 JOIN :
SELECT "Author"."Author_ID", "Author"."Author_FirstName", "Author.Author_LastName", "Adresses"."Street_Coord", "Cities"."City_Name"
FROM "Author"
INNER JOIN "Adresses" ON "Author"."Author_ID"="Adresses"."Author_ID"
INNER JOIN "Cities" ON "Author"."Author_ID"="Cities"."Author_ID"
WHERE "Author"."Author_ID"='X'
没有测试,可能有错别字...
此外,您需要在“地址”和“城市”之间添加一个额外的连接列,以将“1245 Rich st”与“Madrid”、“154 music st”和“Barcelona”相匹配。类似“City_ID”的东西。然后将其添加到 INNER JOIN ... ON 子句中:
INNER JOIN "Cities" ON "Adresses"."City_ID"="Cities"."City_ID" AND "Author"."Author_ID"="Cities"."Author_ID"
【讨论】:
大家好,在现实世界中我有 11 张桌子!当我在 11 个表上使用 JOIN 时,由于返回的记录数量很大,Oracle 崩溃了,这就是我使用 UNION 的原因。我只能用 UNION 找到解决方案。再次感谢! 那么,您可能应该执行多个查询。在您的示例中,您可以执行对作者信息(例如名字和姓氏)的查询,以及对地址和城市的单独查询。这更有意义,并且您将获取比单个大胖查询更少的数据。 嘿 Walloud,这里的人是对的,你应该使用 JOIN 语句而不是 UNION 语句。如果您遇到 ORA-01652 问题,请尝试“调试”它,首先尝试连接 2 个表,然后每次尝试将另一个表添加到您的查询中,并尝试了解哪些表导致查询抛出异常( ORA-01652) , 理解后, 尝试通过添加索引来优化它(例如在目标表中的author_id上)以上是关于优化联合 sql 查询的主要内容,如果未能解决你的问题,请参考以下文章