Sql server 试图理解-IN(带UNION的子查询)

Sql server 试图理解-IN(带UNION的子查询),sql-server,tsql,subquery,union,Sql Server,Tsql,Subquery,Union,我试图理解为什么查询1有效,而查询2无效。工会如何影响执行 我知道存在隐式转换。我不是在寻找修复、最佳实践或性能,只是试图理解其中的原因 DECLARE @T1 TABLE (ID INT, TXT VARCHAR(10)) DECLARE @T2 TABLE (ID INT, T2Fk INT) INSERT INTO @T1 VALUES(1, '1'), (2, '2'), (3, '3'), (4, 'AAA') INSERT INTO @T2 VALUES(1, 1), (2, 3)

我试图理解为什么查询1有效,而查询2无效。工会如何影响执行

我知道存在隐式转换。我不是在寻找修复、最佳实践或性能,只是试图理解其中的原因

DECLARE @T1 TABLE (ID INT, TXT VARCHAR(10))
DECLARE @T2 TABLE (ID INT, T2Fk INT)

INSERT INTO @T1 VALUES(1, '1'), (2, '2'), (3, '3'), (4, 'AAA')
INSERT INTO @T2 VALUES(1, 1), (2, 3)
                    
-- Query 1
SELECT * FROM @T2 WHERE T2Fk IN (SELECT TXT FROM @T1 WHERE ID IN (1,2,3))
-- Query 2
SELECT * FROM @T2 WHERE T2Fk IN (SELECT TXT FROM @T1 WHERE ID IN (1,2) UNION SELECT '3')

谢谢

我不知道为什么第一个SQL运行良好,但第二个SQL运行不好。SQL正在将T2FK从VARCHAR(10)转换为INT,这导致第二次查询失败。最佳做法是使用相同类型的比较值。如果将T2Fk转换为VARCHAR(10),则第二个查询也可以工作

-- Query 2
SELECT * FROM @T2 WHERE CAST(T2Fk AS VARCHAR(10)) IN (SELECT TXT FROM @T1 WHERE ID IN (1,2) UNION SELECT '3')

您的问题是在表定义中,假设SQL接受一个像3这样没有“”的数字,这就是您的第一个查询工作的原因,但是在第二个查询中,您正在尝试将varchar作为Int传递到位置。如果您在T2Fk int中做了一个更改,并将其作为Varchar放入,它将起作用

声明@T1表(ID INT,TXT VARCHAR(10)) 声明@T2表(ID int,T2Fk varchar(10))


然后您的两个查询都将工作

SQL是声明性的。引擎可以自由选择它想要的数据路径-您不能依靠短路来避免逻辑/模式错误。这最终是您的问题。转换的规则是相反的:
TXT
值需要转换为
int
,因为它是“更高”的数据类型。您正在从中的
左侧删除
int
,这样两边都是字符串,不需要转换。@哈波,隐式转换就是我要说的问题所在。虽然SQL正在转换为INT而不是varchar,但您是对的。第一个查询可以工作,因为执行计划在转换之前消除了4个AAA。第二个失败是因为它没有消除该记录。我不明白为什么SQL决定先删除一条记录,而不删除另一条记录。您可以查看每个查询的执行计划,以查看执行操作的顺序。它们有着惊人的不同。至于原因,a可能是查询优化器突发奇想的最佳指南。SMor对OP的评论是正确的:您使用SQL来声明您想要什么,而不是如何获得它。