MySQL 中的自然排序尝试失败

Failed attempts at natural sort in MySQL

我试图在 MySQL 中实现 natural/alphanumeric 排序,但没有成功。我已经阅读了几篇 Stack 文章和关于我在 google 搜索中找到的主题的各种文章。这是我开始的基本查询:

select VideoTitle, VideoID
from Filters
where VideoSource = 'Netflix'
and IMDBSeries = 'tt0367279'
and PublishDate is not null
ORDER BY VideoTitle

该查询产生此结果集:

Arrested Development Season 1: Ep. 1 Pilot
Arrested Development Season 1: Ep. 10 Pier Pressure
Arrested Development Season 1: Ep. 2 Top Banana
Arrested Development Season 1: Ep. 3 Bringing Up Buster
Arrested Development Season 1: Ep. 4 Key Decisions
Arrested Development Season 1: Ep. 5 Charity Drive
Arrested Development Season 1: Ep. 6 Visiting Ours
Arrested Development Season 1: Ep. 7 In God We Trust
Arrested Development Season 1: Ep. 8 My Mother, the Car
Arrested Development Season 1: Ep. 9 Storming the Castle

请注意,从自然排序的角度来看,此行是乱序的:

Arrested Development Season 1: Ep. 10 Pier Pressure

基于我阅读的 posts/articles,我也尝试了这些方法及其附带的结果集:

select VideoTitle
from Filters
where VideoSource = 'Netflix'
and IMDBSeries = 'tt0367279'
and PublishDate is not null
ORDER BY CAST(VideoTitle AS UNSIGNED), VideoTitle
Arrested Development Season 1: Ep. 1 Pilot
Arrested Development Season 1: Ep. 10 Pier Pressure
Arrested Development Season 1: Ep. 2 Top Banana
Arrested Development Season 1: Ep. 3 Bringing Up Buster
Arrested Development Season 1: Ep. 4 Key Decisions
Arrested Development Season 1: Ep. 5 Charity Drive
Arrested Development Season 1: Ep. 6 Visiting Ours
Arrested Development Season 1: Ep. 7 In God We Trust
Arrested Development Season 1: Ep. 8 My Mother, the Car
Arrested Development Season 1: Ep. 9 Storming the Castle

select VideoTitle
from Filters
where VideoSource = 'Netflix'
and IMDBSeries = 'tt0367279'
and PublishDate is not null
ORDER BY LENGTH(VideoTitle), VideoTitle
Arrested Development Season 1: Ep. 1 Pilot
Arrested Development Season 1: Ep. 2 Top Banana
Arrested Development Season 1: Ep. 4 Key Decisions
Arrested Development Season 1: Ep. 5 Charity Drive
Arrested Development Season 1: Ep. 6 Visiting Ours
Arrested Development Season 1: Ep. 10 Pier Pressure
Arrested Development Season 1: Ep. 7 In God We Trust
Arrested Development Season 1: Ep. 3 Bringing Up Buster
Arrested Development Season 1: Ep. 8 My Mother, the Car
Arrested Development Season 1: Ep. 9 Storming the Castle

select VideoTitle
from Filters
where VideoSource = 'Netflix'
and IMDBSeries = 'tt0367279'
and PublishDate is not null
ORDER BY VideoTitle + 0 ASC
Arrested Development Season 1: Ep. 1 Pilot
Arrested Development Season 1: Ep. 9 Storming the Castle
Arrested Development Season 1: Ep. 8 My Mother, the Car
Arrested Development Season 1: Ep. 7 In God We Trust
Arrested Development Season 1: Ep. 6 Visiting Ours
Arrested Development Season 1: Ep. 5 Charity Drive
Arrested Development Season 1: Ep. 4 Key Decisions
Arrested Development Season 1: Ep. 3 Bringing Up Buster
Arrested Development Season 1: Ep. 2 Top Banana
Arrested Development Season 1: Ep. 10 Pier Pressure

有什么想法吗?

如果你真的想要,你可以逐条排序:

order by substring_index(VideoTitle, ' Season ', 1),
         substring_index(VideoTitle, ' Season ', -1) + 0,
         substring_index(VideoTitle, ': Ep. ', -1) + 0

这假设字符串 ' Season ': Ep. 在每个标题中只出现一次。

下面的版本应该也很接近,假设季节只有一个数字:

order by substring_index(VideoTitle, ': Ep. ', 1),
         substring_index(VideoTitle, ': Ep. ', -1) + 0

最好的解决方案是将节目标题、剧季、剧集编号和剧集标题存储在单独的列中。

在这种情况下,您可以进行一些字符串操作来获得所需内容。

ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(VideoTitle, ': ', -1), ' ', 2), ' ', -1)+0 

不过,这是一个非常脆弱的解决方案。

如果创建新列以使您的模型更易于搜索,我会采用更优雅的解决方案,而不是逐个分解字符串。

select VideoTitle 
  from (select VideoTitle, 
               VideoTitle REGEXP '.+Ep\. [0-9]{2}.+' vd2dig 
          from videos
       ) sub
 order by vd2dig, VideoTitle; 

这基本上会使 VideoTitle 有两位数字时变为 1,而当它有一位数字时它将是 0 所以我先按此列排序,然后按自然顺序排序VideoTitle

看到它在这里工作:http://sqlfiddle.com/#!9/6abde/1