【问题标题】:Update Statement with inner join is not evaluating each row带有内部连接的更新语句不评估每一行
【发布时间】:2021-12-27 20:50:45
【问题描述】:

我有一个 Client 表,并且该客户可以有多个 Claims客户索赔都可以有Lead日期。 我希望 ClientLeadDate 为其相关 Claims 的最短日期。

我知道我可以使用带有 Min(LeadDate) 的内联子查询,但我想以另一种方式编写查询。

我想通过内部连接来实现。令我惊讶的是,结果并不是我所期望的。它使用的是遇到的第一个 Claim.LeadDate,这并不总是最小值。

我创建了一个非常小的示例,显示结果不是最小日期。运行下面的查询后,我希望 Client.LeadDate2003-01-01

有人可以帮我理解为什么不是这样吗?

begin tran

select * into #contact
from
    (values(1,convert(Date,'2007-01-01'))) as tmp(ID,LeadDate)

select * into #claim
from
    (values
        (1,1,convert(Date,'2005-01-01')),
        (2,1,convert(Date,'2003-01-01')),
        (3,1,convert(Date,'2004-01-01'))
    ) as tmp(ID,ContactID,LeadDate)

select *,case when cl.LeadDate<co.LeadDate then cl.LeadDate else co.LeadDate end Expected
from
    #contact co
    inner join #claim cl on co.ID=cl.ContactID

update co
    set
        LeadDate=case when cl.LeadDate<co.LeadDate then cl.LeadDate else co.LeadDate end 
from
    #contact co
    inner join #claim cl on co.ID=cl.ContactID

select * from #contact

rollback

【问题讨论】:

  • 你为什么认为它会是任何特定的数据?您对一个联系人有三个声明。如果您将更新更改为选择,您将获得三行。使用它的更新将使用结果集中的第一个日期。
  • 我认为将针对每个匹配行评估该集合,这最终会导致使用最小值。我不确定为什么不是这样。它只是随机选择一行,第一行,最后一行吗?我找不到指导我的文档。
  • 因为行为未定义。在 @t2 上使用和不使用 PRIMARY KEY 运行此程序:dbfiddle.uk/… 如果有多个匹配项并且您希望某个特定的匹配项成为“赢家”,则需要强制 SQL Server 进行操作,否则它只会做最重要的事情高效/最少的工作量。
  • @AaronBertrand 如果它只评估匹配集的单行,那绝对是有道理的。有了这种理解,我可以通过查询或索引强制排序。我仍然很惊讶它只评估一行。感谢您声明它是未定义的。现在我知道为什么我找不到文档了。
  • 以某种间接方式“强制排序”仍然不能使结果具有确定性。可能是“这是我大部分时间都观察到的”,但那是不同的。如果您可以确定哪一行您想成为适用的行,您就不能确定性地做到这一点吗?

标签: sql sql-server tsql sql-update inner-join


【解决方案1】:

As mentioned in the comments,多次更新一行是未定义的行为,通常会导致 SQL Server 只选择一行用于更新。

相反,您可以预先汇总结果

update co
    set
        LeadDate = cl.LeadDate
from #contact co
inner join (
    select
      cl.ContactID,
      LeadDate = MIN(cl.LeadDate)
    from #claim cl
    group by
      cl.ContactID
) cl on co.ID = cl.ContactID;

您也可以使用APPLY 或相关子查询来执行此操作。在某些情况下,您可能需要为此使用行编号。

我必须说,我不同意update 的整个前提。无论如何,您不应该多次存储相同的数据。如果您想计算LeadTime,请在需要时进行计算。除非你真的需要,否则不要去规范化。

【讨论】:

    猜你喜欢
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 2022-12-10
    相关资源
    最近更新 更多