[英]Natural (human alpha-numeric) sort in Microsoft SQL Server
Thank you for taking time to read all this, its a lot!感谢您花时间阅读所有这些,很多! Appreciate all you fellow enthusiasts!向所有热心的小伙伴们致敬!
How to natural sort?如何自然排序?
ie.即。 order a set of alpha numeric data to appear as:将一组字母数字数据排序为:
Season 1, Season 2, Season 10, Season 20
instead of而不是
Season 1, Season 10, Season 2, Season 20
I use a very practical example of tv seasons in a very practical format as case.我以非常实用的格式使用了一个非常实用的电视季节示例作为案例。
I am looking to accomplish the following:我希望完成以下工作:
I spent about 2 hours researching online and another 3 hours building this solution.我花了大约 2 个小时在线研究,另外 3 个小时构建了这个解决方案。 Some of the reference material came from:部分参考资料来自:
Some of the solutions found on SO and other sites only work for 90% of cases.在 SO 和其他站点上找到的一些解决方案仅适用于 90% 的情况。 However, most/all do NOT work if you have multiple numeric values in your text, or will cause SQL error if there isn't a number found in the text at all.但是,如果文本中有多个数值,则大多数/全部都不起作用,或者如果文本中根本没有找到数字,则会导致 SQL 错误。
I have created this SQLFiddle link to play around with (includes all below code).我创建了这个SQLFiddle链接来玩(包括下面的所有代码)。
Here is the create statement:这是创建语句:
create table tvseason
(
title varchar(100)
);
insert into tvseason (title)
values ('100 Season 03'), ('100 Season 1'),
('100 Season 10'), ('100 Season 2'),
('100 Season 4'), ('Show Season 1 (2008)'),
('Show Season 2 (2008)'), ('Show Season 10 (2008)'),
('Another Season 01'), ('Another Season 02'),
('Another 1st Anniversary Season 01'),
('Another 2nd Anniversary Season 01'),
('Another 10th Anniversary Season 01'),
('Some Show Another No Season Number'),
('Some Show No Season Number'),
('Show 2 Season 1'),
('Some Show With Season Number 1'),
('Some Show With Season Number 2'),
('Some Show With Season Number 10');
Here is my working solution (only unable to solve criteria #7 below):这是我的工作解决方案(仅无法解决以下标准#7):
select
title, "index", titleLeft,
convert(int, coalesce(nullif(titleRightTrim2, ''), titleRight)) titleRight
from
(select
title, "index", titleLeft, titleRight, titleRightTrim1,
case
when PATINDEX('%[^0-9]%', titleRightTrim2) = 0
then titleRightTrim2
else left(titleRightTrim2, PATINDEX('%[^0-9]%', titleRightTrim2) - 1)
end as titleRightTrim2
from
(select
title,
len(title) - PATINDEX('%[0-9] %', reverse(title)) 'index',
left(title, len(title) - PATINDEX('%[0-9] %', reverse(title))) titleLeft,
ltrim(right(title, PATINDEX('%[0-9] %', reverse(title)))) titleRight,
ltrim(right(title, PATINDEX('%[0-9] %', reverse(title)))) titleRightTrim1,
left(ltrim(right(title, PATINDEX('%[0-9] %', reverse(title)))), PATINDEX('% %', ltrim(right(title, PATINDEX('%[0-9] %', reverse(title)))))) titleRightTrim2
from
tvseason) x) y
order by
titleLeft, titleRight
Criteria to consider:要考虑的标准:
Here is the output:这是输出:
title
100 Season 1
100 Season 2
100 Season 03
100 Season 4
100 Season 10
**Case 7 here**
Another 10th Anniversary Season 01
Another 1st Anniversary Season 01
Another 2nd Anniversary Season 01
Another Season 01
Another Season 02
Show (2008) Season 1
Show (2008) Season 2
Show 2 The 75th Anniversary Season 1
Show Season 1 (2008)
Show Season 2 (2008)
Show Season 10 (2008)
Some Show Another No Season Number
Some Show No Season Number
Some Show With Season Number 1
Some Show With Season Number 2
Some Show With Season Number 10
I think this will do the trick... I simply recognizes changes from non-numeric to numeric.我认为这可以解决问题......我只是识别从非数字到数字的变化。 I haven't done any large scale testing but It should be reasonably fast.我没有做过任何大规模的测试,但它应该相当快。
SET QUOTED_IDENTIFIER ON;
GO
SET ANSI_NULLS ON;
GO
ALTER FUNCTION dbo.tfn_SplitForSort
/* ===================================================================
11/11/2018 JL, Created: Comments
=================================================================== */
--===== Define I/O parameters
(
@string VARCHAR(8000)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)),
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b),
cte_Tally (n) AS (
SELECT TOP (LEN(@string))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
cte_n2 a CROSS JOIN cte_n2 b
),
cte_split_string AS (
SELECT
col_num = ROW_NUMBER() OVER (ORDER BY t.n) + CASE WHEN LEFT(@string, 1) LIKE '[0-9]' THEN 0 ELSE 1 END,
string_part = SUBSTRING(@string, t.n, LEAD(t.n, 1, 8000) OVER (ORDER BY t.n) - t.n)
FROM
cte_Tally t
CROSS APPLY ( VALUES (SUBSTRING(@string, t.n, 2)) ) s (str2)
WHERE
t.n = 1
OR SUBSTRING(@string, t.n - 1, 2) LIKE '[0-9][^0-9]'
OR SUBSTRING(@string, t.n - 1, 2) LIKE '[^0-9][0-9]'
)
SELECT
so_01 = ISNULL(MAX(CASE WHEN ss.col_num = 1 THEN CONVERT(FLOAT, ss.string_part) END), 99999999),
so_02 = MAX(CASE WHEN ss.col_num = 2 THEN ss.string_part END),
so_03 = MAX(CASE WHEN ss.col_num = 3 THEN CONVERT(FLOAT, ss.string_part) END),
so_04 = MAX(CASE WHEN ss.col_num = 4 THEN ss.string_part END),
so_05 = MAX(CASE WHEN ss.col_num = 5 THEN CONVERT(FLOAT, ss.string_part) END),
so_06 = MAX(CASE WHEN ss.col_num = 6 THEN ss.string_part END),
so_07 = MAX(CASE WHEN ss.col_num = 7 THEN CONVERT(FLOAT, ss.string_part) END),
so_08 = MAX(CASE WHEN ss.col_num = 8 THEN ss.string_part END),
so_09 = MAX(CASE WHEN ss.col_num = 9 THEN CONVERT(FLOAT, ss.string_part) END),
so_10 = MAX(CASE WHEN ss.col_num = 10 THEN ss.string_part END)
FROM
cte_split_string ss;
GO
The function in use...正在使用的函数...
SELECT
ts.*
FROM
#tvseason ts
CROSS APPLY dbo.tfn_SplitForSort (ts.title) sfs
ORDER BY
sfs.so_01,
sfs.so_02,
sfs.so_03,
sfs.so_04,
sfs.so_05,
sfs.so_06,
sfs.so_07,
sfs.so_08,
sfs.so_09,
sfs.so_10;
Results:结果:
id title
----------- ------------------------------------------
2 100 Season 1
4 100 Season 2
1 100 Season 03
5 100 Season 4
3 100 Season 10
11 Another 1st Anniversary Season 01
12 Another 2nd Anniversary Season 01
13 Another 10th Anniversary Season 01
9 Another Season 01
10 Another Season 02
16 Show 2 Season 1
6 Show Season 1 (2008)
7 Show Season 2 (2008)
8 Show Season 10 (2008)
14 Some Show Another No Season Number
15 Some Show No Season Number
17 Some Show With Season Number 1
18 Some Show With Season Number 2
19 Some Show With Season Number 10
--===================================================================== --================================================ ======================
[Edit 2020-09-23] I was looking back at some of my old posts and when I came across this one and wanted to see if I could get to work with a single value output. [编辑 2020-09-23] 我正在回顾我的一些旧帖子,当我遇到这个帖子时,想看看我是否可以开始使用单值输出。 Adding 10 columns to the ORDER BY is just clunky... After a bit of thought, it occurred to me that converting the FLOATs to BINARY and the BINARY back to VARCHAR, I could reassemble the string with the STRING_AGG() function.将 10 列添加到 ORDER BY 只是笨拙的......经过一番思考后,我想到将 FLOAT 转换为 BINARY 并将 BINARY 转换回 VARCHAR,我可以使用 STRING_AGG() 函数重新组装字符串。 The net result would be string that produces the desired sort.最终结果将是产生所需排序的字符串。
CREATE FUNCTION dbo.human_sort_string
/* ===================================================================
09/23/2020 JL, Created: Just a test
=================================================================== */
--===== Define I/O parameters
(
@string varchar(8000)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)), -- 10
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b), -- 100
cte_Tally (n) AS (
SELECT TOP (LEN(@string))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
cte_n2 a CROSS JOIN cte_n2 b -- 10,000
),
cte_Parsed AS (
SELECT
t.n,
parsed_val = SUBSTRING(@string, ISNULL(NULLIF(t.n, 1), 0) + 1, LEAD(t.n, 1, 8000) OVER (ORDER BY t.n) - ISNULL(NULLIF(t.n, 1), 0))
FROM
cte_Tally t
CROSS APPLY ( VALUES (SUBSTRING(@string, t.n, 2)) ) sv (sub_val)
WHERE
t.n = 1
OR
sv.sub_val LIKE '[0-9][^0-9]'
OR
sv.sub_val LIKE '[^0-9][0-9]'
)
SELECT
sort_string = STRING_AGG(ISNULL(CONVERT(varchar(8000), CONVERT(binary(8), TRY_CONVERT(float, p.parsed_val)), 2), p.parsed_val), '') WITHIN GROUP (ORDER BY p.n)
FROM
cte_Parsed p;
GO
Now, the outer query looks like this...现在,外部查询看起来像这样......
SELECT
ts.id,
td.title
FROM
#tvseason ts
CROSS APPLY dbo.human_sort_string(ts.title) hss
ORDER BY
hss.sort_string;
The actual results are identical to the previous function.实际结果与之前的函数相同。
Personally, I would try to avoid doing complex string manipuluation in SQL.就个人而言,我会尽量避免在 SQL 中进行复杂的字符串操作。 I would probably dump it out to a text file and process it using a regular expression in something like C# or Python.我可能会将它转储到一个文本文件中,然后使用 C# 或 Python 之类的正则表达式来处理它。 Then write it back to the DB in a separate column.然后在单独的列中将其写回数据库。 SQL is notoriously bad at string manipulation. SQL 在字符串操作方面是出了名的糟糕。
However here's my stab at a SQL approach.然而,这是我对 SQL 方法的尝试。 The idea is basically to first eliminate any rows which don't have the string Season [number]
in them.这个想法基本上是首先消除任何没有字符串Season [number]
的行。 That handles the case where there are no seasons to parse.这处理没有季节解析的情况。 I chose to include them with nulls, but you could just as easily omit them in your where clause, or give them some default value.我选择将它们包含在空值中,但您也可以轻松地在 where 子句中省略它们,或者给它们一些默认值。 I use the stuff()
function to cut off everything up to the string Season [number]
, so it's easier to work with.我使用stuff()
函数来切断字符串Season [number]
,因此使用起来更容易。
Now we have the string starting with the season number, and potentially ending in some garbage.现在我们有了以季号开头的字符串,并可能以一些垃圾结尾。 I use a case statement to see if there is garbage (anything non-numeric) and if there is, i take the leftmost numeric characters and throw away the rest.我使用 case 语句来查看是否有垃圾(任何非数字的东西),如果有,我取最左边的数字字符并丢弃其余的。 If there is only numeric to begin with, I just leave it as it is.如果只有数字开头,我就保持原样。
Finally, cast it as an int, and sort by it.最后,将其转换为 int,并按它排序。
if object_id('tempdb.dbo.#titles') is not null drop table #titles
create table #titles (Title varchar(100))
insert into #titles (TItle)
select title = '100 Season 1'
union all select '100 Season 2'
union all select '100 Season 03'
union all select '100 Season 4'
union all select '100 Season 10'
union all select 'Another 10th Anniversary Season 01'
union all select 'Another 1st Anniversary Season 01'
union all select 'Another 2nd Anniversary Season 01'
union all select 'Another Season 01'
union all select 'Another Season 02'
union all select 'Show (2008) Season 1'
union all select 'Show (2008) Season 2'
union all select 'Show 2 The 75th Anniversary Season 1'
union all select 'Show Season 1 (2008)'
union all select 'Show Season 2 (2008)'
union all select 'Show Season 10 (2008)'
union all select 'Some Show Another No Season Number'
union all select 'Some Show No Season Number'
union all select 'Some Show With Season Number 1'
union all select 'Some Show With Season Number 2'
union all select 'Some Show With Season Number 10'
;with src as
(
select
Title,
Trimmed = case when Title like '%Season [0-9]%'
then stuff(title, 1, patindex('%season [0-9]%', title) + 6, '')
else null
end
from #titles
)
select
Season = cast(case when Trimmed like '%[^0-9]%' then left(Trimmed, patindex('%[^0-9]%', Trimmed))
else Trimmed
end as int),
Title
from src
order by Season
This question requirement is complex.这个问题要求很复杂。 So it can't be achieved by a simple query.所以不能通过简单的查询来实现。 So my solution is below: First I create a sample data which will be use in this query.所以我的解决方案如下:首先我创建一个将在此查询中使用的示例数据。
CREATE TABLE #TVSEASON (TITLE VARCHAR(100));
INSERT INTO #TVSEASON (TITLE) VALUES
('100'),
('100 SEASON 03'),
('100 SEASON 1'),
('100 SEASON 10'),
('100 SEASON 2'),
('100 SEASON 4'),
('SHOW (2008) SEASON 1'),
('SHOW (2008) SEASON 2'),
('SHOW SEASON 1 (2008)'),
('SHOW SEASON 2 (2008)'),
('SHOW SEASON 10 (2008)'),
('ANOTHER 1ST ANNIVERSARY SEASON 01'),
('ANOTHER 2ND ANNIVERSARY SEASON 01'),
('ANOTHER 10TH ANNIVERSARY SEASON 01'),
('ANOTHER SEASON 01'),
('ANOTHER SEASON 02'),
('SOME SHOW ANOTHER NO SEASON NUMBER'),
('SOME SHOW NO SEASON NUMBER'),
('SHOW 2 THE 75TH ANNIVERSARY SEASON 1'),
('SOME SHOW WITH SEASON NUMBER 1'),
('SOME SHOW WITH SEASON NUMBER 2'),
('SOME SHOW WITH SEASON NUMBER 10')
For the achieved desired result I create a function for split all words and numbers from the text.为了达到预期的结果,我创建了一个函数,用于从文本中拆分所有单词和数字。 (Note: I also remove st from 1st, nd from 2nd etc through function after trim the spaces between 1 st for safe side if any user mistakely type spaces between 1st, so if you think there is no chance of error then you remove LTRIM from that function, because for removing that values it is also remove th if text has value like "1 the title" which will be convert into 1 e title) (注意:如果任何用户错误地在 1st 之间键入空格,我也会在修剪 1 st 之间的空格后通过函数从 1st 中删除 st,从 2nd 等中删除 LTRIM该函数,因为要删除该值,如果文本具有“1 标题”之类的值,它将被转换为 1 e 标题)
--CREATE SPLIT FUNCTION
CREATE FUNCTION [dbo].[SplitAlphaNumeric]
(
@LIST NVARCHAR(2000)
)
RETURNS @RTNVALUE TABLE
(
ID INT IDENTITY(1,1),
WORDS NVARCHAR(100),
NUMBERS INT
)
AS
BEGIN
WHILE (PATINDEX('%[0-9]%',@LIST) > 0)
BEGIN
INSERT INTO @RTNVALUE (WORDS, NUMBERS)
SELECT CASE WHEN PATINDEX('%[0-9]%',@LIST) = 0 THEN @LIST
WHEN (PATINDEX('%[0-9]%',@LIST) = 1 AND PATINDEX('%[^0-9]%',@LIST) = 0) THEN ''
WHEN PATINDEX('%[0-9]%',@LIST) = 1 THEN ''
ELSE SUBSTRING(@LIST, 1, PATINDEX('%[0-9]%',@LIST) - 1)
END,
CASE WHEN PATINDEX('%[0-9]%',@LIST) = 0 THEN NULL
WHEN (PATINDEX('%[0-9]%',@LIST) = 1 AND PATINDEX('%[^0-9]%',@LIST) = 0) THEN CAST(LTRIM(RTRIM(@LIST)) AS INT)
WHEN PATINDEX('%[0-9]%',@LIST) = 1 THEN SUBSTRING(@LIST, 1, PATINDEX('%[^0-9]%',@LIST) - 1)
ELSE NULL
END
SET @LIST = LTRIM(RTRIM(CASE WHEN PATINDEX('%[0-9]%',@LIST) = 0 OR (PATINDEX('%[0-9]%',@LIST) = 1 AND PATINDEX('%[^0-9]%',@LIST) = 0) THEN ''
WHEN PATINDEX('%[0-9]%',@LIST) = 1 THEN
CASE WHEN LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST)))) LIKE 'ST%' THEN SUBSTRING(LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST)))),3, LEN(LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST))))))
WHEN LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST)))) LIKE 'ND%' THEN SUBSTRING(LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST)))),3, LEN(LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST))))))
WHEN LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST)))) LIKE 'RD%' THEN SUBSTRING(LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST)))),3, LEN(LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST))))))
WHEN LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST)))) LIKE 'TH%' THEN SUBSTRING(LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST)))),3, LEN(LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST))))))
ELSE LTRIM(SUBSTRING(@LIST, PATINDEX('%[^0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[^0-9]%',REVERSE(@LIST))))
END
ELSE SUBSTRING(@LIST, PATINDEX('%[0-9]%',@LIST), LEN(@LIST)-PATINDEX('%[0-9]%',REVERSE(@LIST)))
END))
END
INSERT INTO @RTNVALUE (WORDS)
SELECT VALUE = LTRIM(RTRIM(@LIST))
RETURN
END
In third step I use cross apply on calling function because function return table against given string value.在第三步中,我在调用函数时使用交叉应用,因为函数返回表针对给定的字符串值。 On select query I insert all columns into temp table for sort values as per requirement in next step.在选择查询时,我将所有列插入到临时表中,以便根据下一步的要求对值进行排序。
SELECT T.TITLE, A.ID, A.NUMBERS, A.WORDS INTO #FINAL
FROM #TVSEASON T
CROSS APPLY dbo.SplitAlphaNumeric(TITLE) A
From the temp table #Final I use stuff for concate all words to make title again without any number occurence in the text, and then use that values to order the title.从临时表 #Final 我使用内容连接所有单词以再次制作标题,文本中不出现任何数字,然后使用该值对标题进行排序。
You can change that query for order in any sequence like if you want to order against the text then you order first textval column then numbers, but if you want to order against summation of all the numbers which are used in title then order numbers first after sum like I do or else if you want to order on simple number without sum then don't use group by clause and subquery and directly order against numbers.您可以按任何顺序更改该订单查询,例如,如果您想根据文本进行排序,则先对 textval 列进行排序,然后再对数字进行排序,但是如果您想针对标题中使用的所有数字的总和进行排序,则在排序之后先排序sum 像我一样,否则如果你想在没有 sum 的简单数字上排序,那么不要使用 group by 子句和子查询,直接对数字排序。 In short you can achieved all the sequences respected to alpha numeric values after modify that below query and the upper one are the base query for all the goals.简而言之,您可以在修改下面的查询后实现所有符合字母数字值的序列,上面的查询是所有目标的基本查询。
SELECT A.TITLE--, A.NUMBERS, A.TEXTVAL
FROM (
SELECT A.TITLE,
STUFF((
SELECT ' ' + B.WORDS
FROM #FINAL B
WHERE B.TITLE = A.TITLE
FOR XML PATH(''),TYPE).VALUE('(./TEXT())[1]','VARCHAR(MAX)')
,1,1,'') TEXTVAL,
SUM(ISNULL(A.NUMBERS,0)) NUMBERS
FROM #FINAL A
GROUP BY A.TITLE
) A
ORDER BY A.TEXTVAL, A.NUMBERS
DROP TABLE #FINAL
DROP TABLE #TVSEASON
In last I drops both temp table from memory.最后,我从内存中删除了两个临时表。 I think it is the query for sorting values which you want because if anyone have different order requirement agains alphanumeric values they can achieved their requirement after litle bit modify that query.我认为这是对您想要的值进行排序的查询,因为如果有人对字母数字值有不同的顺序要求,他们可以在稍微修改该查询后实现他们的要求。
My answer takes advantage of OPEN_JSON to split each title into words, it then replaces numbers with the same number of 'a's.我的答案利用 OPEN_JSON 将每个标题拆分为单词,然后用相同数量的 'a' 替换数字。 eg 2 becomes aa and 10 becomes aaaaaaaa.例如,2 变为 aa,10 变为 aaaaaaaa。 This leaves us with a set of rows, 1 for each word.这给我们留下了一组行,每个单词 1。 I then join these back together again using STRING_AGG within each title to create a new title containing the numbers replaced with a's.然后我在每个标题中使用 STRING_AGG 再次将这些重新连接在一起,以创建一个包含替换为 a 的数字的新标题。 I then sort by this and report the original title:然后我按此排序并报告原始标题:
with Words1 as
(
select title, REPLACE(REPLACE(value, '(', ''), ')', '') word, [key] as RowN
from tvseason
CROSS APPLY OPENJSON('["' +
REPLACE(REPLACE(REPLACE(title,' ','","'),'\','\\"'),'"','\"') +
'"]')
),
Words2
AS
(
SELECT title,
CASE
WHEN ISNUMERIC(word) = 1 THEN Replicate('a', CAST(Word as INT))
WHEN word like '%st' AND ISNUMERIC(LEFT(word, LEN(Word)-2)) = 1
THEN Replicate('a', CAST(LEFT(Word, LEN(Word)-2) as INT))
WHEN word like '%nd' AND ISNUMERIC(LEFT(word, LEN(Word)-2)) = 1
THEN Replicate('a', CAST(LEFT(Word, LEN(Word)-2) as INT))
WHEN word like '%rd' AND ISNUMERIC(LEFT(word, LEN(Word)-2)) = 1
THEN Replicate('a', CAST(LEFT(Word, LEN(Word)-2) as INT))
WHEN word like '%th' AND ISNUMERIC(LEFT(word, LEN(Word)-2)) = 1
THEN Replicate('a', CAST(LEFT(Word, LEN(Word)-2) as INT))
else Word
END As Word,
rowN
from words1
),
Words3
AS
(
SELECT title, STRING_AGG(Word, ' ') WITHIN GROUP (Order By rowN ASC) AS TitleLong
FROM Words2
GROUP BY Title
)
SELECT title
FROM Words3
ORDER BY TitleLong
This gives the following results:这给出了以下结果:
**title**
100 Season 1
100 Season 2
100 Season 03
100 Season 4
100 Season 10
Another 1st Anniversary Season 01
Another 2nd Anniversary Season 01
Another 10th Anniversary Season 01
Another Season 01
Another Season 02
Show 2 Season 1
Show Season 1 (2008)
Show Season 2 (2008)
Show Season 10 (2008)
Some Show Another No Season Number
Some Show No Season Number
Some Show With Season Number 1
Some Show With Season Number 2
Some Show With Season Number 10
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.