【发布时间】:2021-12-27 20:50:45
【问题描述】:
我有一个 Client 表,并且该客户可以有多个 Claims。 客户和索赔都可以有Lead日期。 我希望 Client 的 LeadDate 为其相关 Claims 的最短日期。
我知道我可以使用带有 Min(LeadDate) 的内联子查询,但我想以另一种方式编写查询。
我想通过内部连接来实现。令我惊讶的是,结果并不是我所期望的。它使用的是遇到的第一个 Claim.LeadDate,这并不总是最小值。
我创建了一个非常小的示例,显示结果不是最小日期。运行下面的查询后,我希望 Client.LeadDate 为 2003-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