在此示例代码中,我看不到为什么比较失败:
create table #a(a nvarchar(10))
insert #a values( 1 )
insert #a values( 2 )
insert #a values( 3 )
insert #a values('A')
select * from (select * from #a where a not like 'A%') b where a < 2
drop table #a
我了解到它失败,并包含alpha值,因为转换为int失败,但是当我将其从候选行集b中明确排除时,为什么仍尝试转换第四行?如果我通过将b编写为表格将其分成两部分,则可以正常工作。也就是说,这是
create table #a(a nvarchar(10))
insert #a values( 1 )
insert #a values( 2 )
insert #a values( 3 )
insert #a values('A')
select * into #b from (select * from #a where a not like 'A%') b
select * from #b where a < 2
drop table #a
drop table #b
...有效。我想念什么?这是Azure SQL。
答案 0 :(得分:3)
查询优化器可以自由执行predicate pushdown之类的任何优化:
select * from (select * from #a where a not like 'A%') b where a < 2
=>
select * from #a where a not like 'A%' and a < 2;
-- the order of execution is not guaranteed so it tries comparison 'A' < 2
-- VARCHAR vs INT, INT has higher data type precedence, implicit conversion to INT
为了避免像第二个示例那样必须实现子查询。
不幸的是,SQL Server尚不支持实体化提示:https://feedback.azure.com/forums/908035-sql-server/suggestions/32642629-t-sql-common-table-expression-materialize-option
答案 1 :(得分:0)
我测试并发现这些查询也有效:
create table #a(a nvarchar(10))
insert #a values( 1 )
insert #a values( 2 )
insert #a values( 3 )
insert #a values('A')
insert #a values('B')
--query1
select * from (select * from #a where a not like 'A%') b where a < '2'
--query2
select * from #a where a < '2' and a not like 'A%'
--query3
select * from #a where a < '2'
drop table #a
根据文档,implicit conversions可以将nvarchar
转换为int
。
将nvarchar
数据类型与int
数据类型进行比较,SQL Server会将所有“ a”列值转换为int
。但并非所有值都可以转换:
但是,如果将int
转换为nvarchar
,则查询有效。
希望这会有所帮助。