在更新一个表的列相对于另一个表的列时避免多个 SELECT
Posted
技术标签:
【中文标题】在更新一个表的列相对于另一个表的列时避免多个 SELECT【英文标题】:Avoid multiple SELECT while updating a table's column relatively to another table's one 【发布时间】:2018-11-30 10:22:39 【问题描述】:我是一个 SQL 查询的新手,但我需要相对于另一个表的列来修改一个表的列。现在我有以下查询工作:
UPDATE table1
SET date1=(
SELECT last_day(max(date2))+1
FROM table2
WHERE id=123
)
WHERE id=123
AND date1=to_date('31/12/9999', 'dd/mm/yyyy');
这个结构的问题在于,我想,SELECT 查询将针对table1
的每一行执行。所以我尝试创建另一个查询,但是这个查询在 FROM
关键字之后的某处有语法错误:
UPDATE t1
SET t1.date1=last_day(max(t2.date2))+1
FROM table1 t1
INNER JOIN table2 t2
ON t1.id=t2.id
WHERE t1.id=123
AND t1.date1=to_date('31/12/9999', 'dd/mm/yyyy');
除此之外,我什至不知道这个是否比第一个快......
你知道我该如何处理这个问题吗?
非常感谢!
亲切的问候,
朱利安
【问题讨论】:
【参考方案1】:您编写的第一个代码很好。正如您所担心的,它不会对table1
的每一行都执行。它将执行以下操作:
UPDATE
语句中使用的值,搜索table2
,但正如您所说的确切id
来自
桌子,它应该尽可能快,只要你有
在那个(我猜是主键)列上创建了一个索引
它将运行外部查询,找到您要更新的单行。和以前一样,只要该列上有索引,它就应该尽可能快,就像您所说的确切 id
一样。
总而言之,如果这些 ID 是唯一的,那么您的子查询和查询都应该只返回一行,并且应该尽可能快地执行。如果您认为执行速度不够快(至少它花费的时间比数据量所证明的要长),请检查这些列是否具有唯一值以及它们是否具有唯一索引。
事实上,最好添加这些索引而不考虑这个问题,如果它们不存在并且这些列具有唯一值,因为它会显着提高这些表上搜索这些 id 列的所有性能.
【讨论】:
感谢您的详细解释!实际上,我有几行具有相同的 id 列,这就是为什么我担心它会多次查找最大日期。我是否需要找到一种方法来存储一次最大日期值,例如“全局变量”,或者您是否推荐其他方法?再次感谢! 不错!感谢您的专业知识!那我接受这个答案!【参考方案2】:请尝试使用 MERGE
MERGE INTO (
SELECT id,
date1
FROM table1
WHERE date1 = to_date('31/12/9999', 'dd/mm/yyyy')
AND id = 123
) t1
USING (
SELECT id,
last_day(max(date2))+1 max_date
FROM table2
WHERE id=123
GROUP BY id
) t2 ON (t1.id = t2.id)
WHEN MATCHED THEN
UPDATE SET t1.date1 = t2.max_date
;
【讨论】:
感谢您的回答。我尝试了这个查询,但它比第一个查询慢(在我的示例中为 173 秒,而之前为 77 秒)。我有几行具有相同的 id,也许这就是它变慢的原因? 您不应查看执行时间,而应查看缓冲区获取的数量。但是,如果您想中继执行时间,请执行几次,拒绝第一次执行的时间并计算平均值。 我按照你的建议做了,上面的查询在执行时间上稍微好一点,所以我会保留这个。再次感谢您,有几种方法总是好的!以上是关于在更新一个表的列相对于另一个表的列时避免多个 SELECT的主要内容,如果未能解决你的问题,请参考以下文章