带有select和order by的tsql字符串concat不适用于order by子句中的函数?

带有select和order by的tsql字符串concat不适用于order by子句中的函数?,sql,sql-server,tsql,Sql,Sql Server,Tsql,考虑以下tsql create function dbo.wtfunc(@s varchar(50)) returns varchar(10) begin return left(@s, 2); end GO select t.* into #test from ( select 'blah' as s union select 'foo' union select 'bar' ) t select * from #test; declare @s varchar(10

考虑以下tsql

create function dbo.wtfunc(@s varchar(50)) returns varchar(10) begin return left(@s, 2); end
GO
select t.* into #test from (
    select 'blah' as s union
    select 'foo' union
    select 'bar'
) t
select * from #test;

declare @s varchar(100); 
set @s = '';

select @s = @s + s from #test order by s;
select @s;
set @s = '';
select @s = @s + s from #test order by dbo.wtfunc(s);
select @s;
/* 2005 only*/
select cast((select s+'' from #test order by dbo.wtfunc(s) for xml path('')) as varchar(100))

drop function dbo.wtfunc;
drop table #test;
我已经在mssql 2000和2005上尝试过了,当使用order by中的函数时,这两种方法都不会压缩字符串。在2005年,for xml路径(“”)起作用。输出是

bar
blah
foo

barblahfoo

foo --nothing concatenated?

barblahfoo
我找不到这是在哪里记录的。有人能解释一下为什么这不起作用吗

编辑:

以下是实际执行计划。显然,排序和计算标量的顺序不同


我不知道这是否有帮助,但当我尝试这一点时:

set @s = '          ';

select @s = @s + s from #test order by dbo.wtfunc(s);
select @s AS myTest
我明白了(注意在'foo'前面有空格,后面没有空格):


我猜这是个不起眼的小虫子

这似乎是一个错误

从链接:


ANSI SQL-92规范要求ORDER by子句引用的任何列都与SELECT列表中的列定义的结果集相匹配。当表达式应用于ORDER by子句的成员时,该结果列不会在SELECT列表中公开,从而导致未定义的行为

您可以使用计算列来完成此操作,例如:

DROP TABLE dbo.temp;

CREATE TABLE dbo.temp
(
  s varchar(20)
 ,t AS REVERSE(s)
);
INSERT INTO dbo.temp (s) VALUES ('foo');
INSERT INTO dbo.temp (s) VALUES ('bar');
INSERT INTO dbo.temp (s) VALUES ('baz');
INSERT INTO dbo.temp (s) VALUES ('blah');
GO

-- Using the function directly doesn't work:
DECLARE @s varchar(2000);
SELECT s, REVERSE(s) FROM dbo.temp ORDER BY REVERSE(s);
SET @s = '';
SELECT @s = @s + s FROM dbo.temp ORDER BY REVERSE(s);
SELECT @s;
GO

-- Hiding the function in a computed column works:
DECLARE @s varchar(2000);
SELECT s, t FROM dbo.temp ORDER BY t;
SET @s = '';
SELECT @s = @s + s FROM dbo.temp ORDER BY t;
SELECT @s;
GO

是的,我不知道是怎么回事。似乎只使用最后一行。因为如果你把它改成“desc”,你只会得到“bar”。完全忘记了计算列。嗯,现在我需要决定是否要在我的桌子上放一个……不过这是一个很好的提示!
DROP TABLE dbo.temp;

CREATE TABLE dbo.temp
(
  s varchar(20)
 ,t AS REVERSE(s)
);
INSERT INTO dbo.temp (s) VALUES ('foo');
INSERT INTO dbo.temp (s) VALUES ('bar');
INSERT INTO dbo.temp (s) VALUES ('baz');
INSERT INTO dbo.temp (s) VALUES ('blah');
GO

-- Using the function directly doesn't work:
DECLARE @s varchar(2000);
SELECT s, REVERSE(s) FROM dbo.temp ORDER BY REVERSE(s);
SET @s = '';
SELECT @s = @s + s FROM dbo.temp ORDER BY REVERSE(s);
SELECT @s;
GO

-- Hiding the function in a computed column works:
DECLARE @s varchar(2000);
SELECT s, t FROM dbo.temp ORDER BY t;
SET @s = '';
SELECT @s = @s + s FROM dbo.temp ORDER BY t;
SELECT @s;
GO