tsql строка concat с select и order by не работает с функцией order by? - PullRequest
4 голосов
/ 11 июня 2009

Рассмотрим следующее 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, и оба не объединяют строку при использовании функции в порядке. В 2005 году путь for xml ('') работает. Выходной сигнал ...

bar
blah
foo

barblahfoo

foo --nothing concatenated?

barblahfoo

Я не могу найти, где это задокументировано. Может кто-нибудь пролить свет на то, почему это не работает?

EDIT:

Вот фактические планы выполнения. Очевидно, что сортировка и вычисление скаляров не в том же порядке ...

alt text alt text

Ответы [ 3 ]

5 голосов
/ 12 июня 2009

Может показаться, что это известная проблема с Совокупными запросами конкатенации .

Из ссылки:

"Спецификация ANSI SQL-92 требует, чтобы любой столбец, на который ссылается предложение ORDER BY, соответствовал результирующему набору, определенному столбцами, присутствующими в списке SELECT. Когда выражение применяется к члену ORDER BY условие, что результирующий столбец не отображается в списке SELECT, что приводит к неопределенному поведению. "

3 голосов
/ 12 июня 2009

Вы можете сделать это, используя вычисляемый столбец, например:

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
2 голосов
/ 11 июня 2009

Я не знаю, полезно ли это вообще, но когда я пытаюсь это сделать:

set @s = '          ';

select @s = @s + s from #test order by dbo.wtfunc(s);
select @s AS myTest

Я получаю это (обратите внимание, что перед 'foo' есть пробелы, но ни один из них не заканчивается):

  foo

Полагаю, это какая-то неясная маленькая ошибка?!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...