【问题标题】:SQLite - Sort alphanumerically while ignoring special characters and "The"SQLite - 在忽略特殊字符和“The”的同时按字母数字排序
【发布时间】:2012-07-14 17:31:27
【问题描述】:

我正在开发一个 iOS 应用程序,该应用程序使用 FMDB 存储必须按字母数字排序的书名列表(字母第一,数字第二)。但是,我还必须忽略非字母数字前导字符,例如星号或括号。我也必须忽略“The”。此外,这些排序后的数据将显示在索引 UITableView 上,因此我需要能够获取前导字符列表以及进入每个部分的书名数量。

例子-

这是书名列表:

"A Title 1", "A Title 2", "The A Title 3", "B Title 1", "B Title 2", "B Title 3", 
"*B Title 4", "C Title 1", "(The) C Title 2", "3 Title 1"

从这个列表中,我会计算 4 个部分来将标题放在('A'、'B'、'C'、'3')中。我还会计算进入每个部分的书的数量('A'-3 书,'B'-4 书,'C'-2 书,'3'-1 书)。使用this tutorial,我能够设置部分和索引,但在处理“The A Title 3”、“*B Title 4”和“(The) C Title 2”等标题时遇到了麻烦。

目前,这是我正在使用的语句:

SELECT DISTINCT UPPER(SUBSTR(BookTitle, 1, 1)) AS Section, 
COUNT(BookTitle) AS SectionCount 
FROM BookTable 
GROUP BY Section ORDER BY IFNULL(Section + 1, 0), Section

这将返回按字母数字排序的章节列表以及进入每个章节的书籍数量。问题是我的“T”部分有太多书籍,因为它正在获取所有以“The”为主角的书籍。更不用说当我想忽略这些特殊字符时,我会得到像

我希望这足够详细。请随时要求我澄清任何事情。一如既往,提前致谢。

【问题讨论】:

  • 您通常需要创建第二个“已清理”的标题列。它可以纯粹用于查询,然后在显示结果时返回原始列。
  • @HotLicks 是的,我就是这么想的。我只是不确定所需的语法或在哪里可以找到完整的 SQLite 函数列表。
  • 您不需要任何新语法即可将另一列添加到您的数据库中。只需在创建第一列数据时创建第二列数据,然后将两者插入在一起。然后,不是在第一个中搜索匹配项,而是在第二个中搜索。但在您检索的列中包含第一列。
  • “SQLite 函数综合列表”在documentation website.

标签: sql ios sqlite indexing


【解决方案1】:

最好的选择可能是在插入时检查这些条件,并将“The”放在标题的末尾(例如,“A Title 3, The”)。您可以编写一个简单的程序来更新当前数据库并将“The”标记到末尾。

但是,如果您真的想保持这种方式,请查看 case 表达式。这是一个相关主题: Does sqlite support any kind of IF(condition) statement in a select

基本上,检查“The”或特殊字符的大小写,并在您的 SUBSTR 中使用该大小写。

【讨论】:

    【解决方案2】:

    与其他语言相比,SQL 中的字符串操作通常是“返璞归真”。以下是您可以采取的一种方法:

    select upper(substring(titleclean, 1, 1)) as Section, count(*)
    from (select bt.*,
                 (case when upper(substring(titletrim, 1, 4)) = 'THE ' or
                            upper(sutring(titletim, 1, 5)) = 'THE) '
                       then substring(titletrim, 5, 1000)
                       else titletrim
                  end) as titleclean
          from (select bt.*, ltrim(title, '()*') as titletrim
                from booktable bt
               ) bt
         ) bt
    group by upper(substring(titleclean, 1, 1))
    order by (case when substring(titleclean, 1, 1) between '0' and '9' then 1
                   else 0
              end),
             Section
    

    这是通过在子查询中分配变量来进行字符串操作。我认为这些遵循您想要的规则。最里面的 ltrim() 是删除你不想要的初始变量。

    我将表达式“ifnull(section+1, 0)”更改为更清晰的范围比较。您的版本可能适用于 SQLite。在大多数数据库中,它会为非数字部分生成错误。

    【讨论】:

    • 谢谢。 SQLite 的语法有点有限,所以我看看能不能翻译一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 2019-12-01
    • 2011-04-06
    相关资源
    最近更新 更多