0

例如:

  • 公寓中的 101 柱
  • 祖祖杜尔加国际酒店
  • 新鲜草地温德姆花园酒店

需要将上述排序为,

  • 101栋位于Pillars的公寓
  • 杜尔加国际酒店 祖祖
  • 新鲜花园草地温德姆酒店
4

3 回答 3

6

试试这个:

DECLARE @tbl TABLE(YourString VARCHAR(100));
INSERT INTO @tbl VALUES
 ('Pillars 101 in an apartment')
,('Zuzu Durga International Hotel')
,('Wyndham Garden Fresh Meadows');

SELECT CAST('<x>' + REPLACE((SELECT YourString AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML).query
('
    for $x in /x
    order by $x
    return
    concat($x/text()[1], " ")   
').value('.','varchar(max)')
FROM @tbl; 

该代码将首先以 XML 格式传输您的文本,例如<x>Pillars</x><x>101</x> ....
然后 aFLWOR XQuery用于返回已排序的文本部分。
最后一次调用.value()将再次将排序的片段作为文本返回。

结果

101  Pillars  an  apartment  in 
Durga  Hotel  International  Zuzu 
Fresh  Garden  Meadows  Wyndham 

最后声明

这段代码是一种练习。你的设计真的很糟糕,应该改变......

于 2018-01-05T12:33:34.010 回答
1

因此,您无法在本地进行任何操作。如果您只想将值排序为返回值,即不更新数据库本身,您可以使用存储过程或视图转换结果。

因此,让我们构建一个答案。

让我们假设您想以视觉方式完成单行。如果你有 SQL 2016,你可以使用STRING_SPLIT但 SQL Fiddle 没有,所以我使用了一个常见的 UDF fnSplitString

http://sqlfiddle.com/#!6/7194d/2

SELECT value FROM fnSplitString('Pillars 101 in an apartment', ' ') WHERE RTRIM(value) <> '';

这给了我每一个字,分开。订购它怎么样?

SELECT value FROM fnSplitString('Pillars 101 in an apartment', ' ') WHERE RTRIM(value) <> '' ORDER BY value;

如果我想为我拥有的数据库表中的每一行执行此操作?http://sqlfiddle.com/#!6/7194d/8

SELECT split.value FROM [Data] d CROSS APPLY dbo.fnSplitString(IsNull(d.Value,''), ' ') AS split WHERE RTRIM(split.value) <> '' ORDER BY value;

这有点帮助,只是现在我所有的词都乱七八糟了。让我们回到我们的原始查询并识别每一行。每行可能都有一个标识列。如果是这样,您的分组就在那里。如果没有,可以使用 ROW_NUMBER,如:

SELECT ROW_NUMBER() OVER(ORDER BY d.Value) AS [Identity] -- here, use identity instead of row_number , d.Value FROM [Data] d

如果我们在我们的选择中使用这个查询作为子查询,我们得到:

http://sqlfiddle.com/#!6/7194d/21

SELECT d.[Identity], split.value FROM ( SELECT ROW_NUMBER() OVER(ORDER BY d.Value) AS [Identity] -- here, use identity instead of row_number , d.Value FROM [Data] d ) d CROSS APPLY dbo.fnSplitString(IsNull(d.Value,''), ' ') AS split WHERE RTRIM(split.value) <> '' ORDER BY d.[Identity], value;

此查询现在对每个身份中的所有行进行排序。但是现在您需要将这些单独的单词重构回单个字符串,对吗?为此,您可以使用STUFF在我的示例中,由于 SQL Fiddle 限制,我使用CTE,但您也可以使用临时表。

WITH tempData AS ( SELECT d.[Identity], split.value FROM ( SELECT ROW_NUMBER() OVER(ORDER BY d.Value) AS [Identity] -- here, use identity instead of row_number , d.Value FROM [Data] d ) d CROSS APPLY dbo.fnSplitString(IsNull(d.Value,''), ' ') AS split WHERE RTRIM(split.value) <> '' ) SELECT grp.[Identity] , STUFF((SELECT N' ' + [Value] FROM tempData WHERE [Identity] = grp.[Identity] ORDER BY Value FOR XML PATH(N'')) , 1, 1, N'') FROM (SELECT DISTINCT [Identity] FROM tempData) AS grp

这是最终结果小提琴:http ://sqlfiddle.com/#!6/7194d/27

正如评论中已经表达的那样,这不是 SQL 的常见情况。这对服务器来说是不必要的负担。我建议从 SQL 中提取数据并通过您选择的编程语言对其进行排序;或确保在将其插入数据库时​​对其进行排序。我进行了练习,因为我有几分钟的时间可以杀死:)

于 2018-01-05T12:26:29.470 回答
1

Shnugo 的解决方案已经 +1。我其实在关注他的帖子。

只是另一个选项将解析 UDF 与交叉应用结合使用。

例子

Select B.*
 From  YourTable A
 Cross Apply ( Select Sorted=Stuff((Select ' ' +RetVal From [dbo].[tvf-Str-Parse](A.SomeCol,' ') Order By RetVal For XML Path ('')),1,1,'')  )B

退货

Sorted
101 an apartment in Pillars
Durga Hotel International Zuzu
Fresh Garden Meadows Wyndham

有兴趣的UDF

CREATE FUNCTION [dbo].[tvf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (  
    Select RetSeq = Row_Number() over (Order By (Select null))
          ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
    From  (Select x = Cast('<x>' + replace((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i)
);
--Thanks Shnugo for making this XML safe
--Select * from [dbo].[tvf-Str-Parse]('Dog,Cat,House,Car',',')
于 2018-01-05T14:10:04.057 回答