【问题标题】:Aliasing Table in SQL Server and Using ExistsSQL Server 中的别名表和使用 Exists
【发布时间】:2019-05-15 23:38:06
【问题描述】:

我正在尝试准确了解 Exists 的工作原理,因此我制作了这个快速临时表来尝试了解它。

Drop Table #mytesttable
create table #mytesttable (edate date, num decimal(4,0), stat varchar(8),etype varchar(12))
insert into #mytesttable 
values ('20180401',1,'E','A/W'),
('20180101',1,'E','A/W'),
('20180701',1,'E','A/W'),
('20181001',1,'E','A/W'),
('20190101',1,'E','A'),
('20190301',1,'I','NULL'),
('20190101',2,'E','A'),
('20190301',2,'E','A'),
('20180901',2,'E','A'),
('20190101',3,'E','NULL'),
('20190301',3,'I','NULL'),
('20180901',3,'I','NULL')

在执行下面的查询时,我得到了三行返回,而我预计只有 1 行。

Select *
From #mytesttable
Where edate = '20190101'
and stat = 'E'
and exists(Select *
From #mytesttable sub
Where  sub.num = num
and sub.etype  = 'A/W'
and sub.edate < '20190101')

结果:

edate   num stat    etype
2019-01-01  1   E   A
2019-01-01  2   E   A
2019-01-01  3   E   NULL

当我在顶部查询中使用表的全名来引用我匹配的存在语句中的列名时,我得到了我期望的结果。

Select *
From #mytesttable
Where edate = '20190101'
and stat = 'E'
and exists(Select *
From #mytesttable sub
Where  sub.num = #mytesttable.num
and sub.etype  = 'A/W'
and sub.edate < '20190101')

结果(正确):

edate   num stat    etype
2019-01-01  1   E   A

exists 语句也因此感到困惑,并认为它与 #mytesttable 中的 num 匹配。也就是说,是不是这样看的:

#mytesttable inner join #mytesttable
on num = num

一旦计算结果为 True,它甚至都不查看 Where 子句?如果有人能对此有所了解,那就太棒了。

【问题讨论】:

  • 限定所有列引用;最佳实践是为每个表引用分配一个 unique 别名,然后使用唯一别名限定列引用。 (即使您不需要,它也将使任何未来的读者更清楚意图。)例如,为最外层的表引用分配一个别名。 t,然后限定存在子查询 sub.num = t.num 中的引用。 (我们很清楚......这不是 EXISTS 的问题,而是 SQL 如何解析列引用的问题,首先查看最内层/最近的 FROM 子句,然后再查看外部查询)
  • @spencer7593 感谢您的澄清。我认为通过在存在语句中为表起别名,它会阻止“num”在那里解析名称引用。我错了。
  • sub 别名和使用sub. 限定列引用都很好。这没什么不好。问题只是不合格的列引用。而这个问题是我们推荐模式的原因之一:“为每个表引用分配唯一的表别名”和“限定所有列引用”

标签: sql sql-server tsql subquery exists


【解决方案1】:

它与列的范围/可见性有关:

Subqueries

一般规则是语句中的列名由同级FROM子句引用的表隐式限定。如果FROM子句引用的表中不存在列对于子查询,它由外部查询的 FROM 子句中引用的表隐式限定。

所以您的第一个查询已加入:

From #mytesttable sub
Where  sub.num = num
<=>
FROM #mytesttable sub
WHERE sub.num = sub.num   --always true for NOT NULL column

我建议遵循EIBTI('Explicit Is Better Than Implicit') 原则,用表别名显式限定所有列。

【讨论】:

  • 感谢您的回答和参考。我将努力遵循息税前利润本金。这是我最常忽略的事情之一,它仍然可以正常工作,但我可以看到这对我未来的影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
  • 2021-08-29
  • 2019-05-14
  • 1970-01-01
  • 2021-10-16
  • 2023-01-17
相关资源
最近更新 更多