在更新一个表的列相对于另一个表的列时避免多个 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的主要内容,如果未能解决你的问题,请参考以下文章

MS Access 在多个表的列字段中查找和替换文本

如何用另一个表的列值更新一个表的列值? [复制]

如何通过数组的每个元素一个一个地更新表的列?

SQL:根据另一个表的计数结果更新一个表中的列

用另一个表中的随机条目更新表的列

跨多个表的列的 SQL 唯一约束