【问题标题】:MSSQL collation for correct sorting of nvarchar field with emojis用于正确排序带有表情符号的 nvarchar 字段的 MSSQL 排序规则
【发布时间】:2021-11-05 10:33:30
【问题描述】:

我想知道我应该使用哪种排序规则来为包含文本和表情符号的 nvarchar 列获得一致的排序。 无论如何,预期的结果是这样的(按 MS Excel 排序):

第一次尝试:SQL_Latin1_General_CP1_CI_AI

SELECT Val
FROM (VALUES
    (N'⭐⭐⭐'),
    (N'⭐⭐⭐'),
    (N'????'),
    (N'⭐⭐'),
    (N'⭐⭐'),
    (N'????????'),
    (N'⭐'),
    (N'❗❗'),
    (N'❗❗'),
    (N'❗'),
    (N'❗'),
    (N'❗❗❗'),
    (N'❗❗❗'),
    (N'bb'),
    (N'ab'),
    (N'aa')
) AS A (Val)
ORDER BY Val COLLATE SQL_Latin1_General_CP1_CI_AI

结果(与预期不同):

第二次尝试(基于此答案https://stackoverflow.com/a/47551803/2336493):Latin1_General_100_CI_AS_SC

SELECT Val
FROM (VALUES
    (N'⭐⭐⭐'),
    (N'⭐⭐⭐'),
    (N'????'),
    (N'⭐⭐'),
    (N'⭐⭐'),
    (N'????????'),
    (N'⭐'),
    (N'❗❗'),
    (N'❗❗'),
    (N'❗'),
    (N'❗'),
    (N'❗❗❗'),
    (N'❗❗❗'),
    (N'bb'),
    (N'ab'),
    (N'aa')
) AS A (Val)
ORDER BY Val COLLATE Latin1_General_100_CI_AS_SC;

结果(与预期不同):

有人处理过吗?

【问题讨论】:

  • 你为什么认为这是正确的顺序?为什么 ASCII 字符串会排在 any emoji 之后? aa-bb 应该总是出现在任何以表情符号开头的文本之前。无论如何,没有一种语言有表情符号,所以不应该期望正常的排序规则来对它们进行排序。
  • @PanagiotisKanavos 我同意你的观点,但这个顺序是我在写这个问题时发现的最准确的。
  • 根本不准确。 ASCII 字母不能出现在 40 年后添加的表情符号之后。 Excel 在这种情况下使用自己的规则,可能通过一些奇怪的转换将所有值都视为数字
  • 当我在 Excel for Mac 中尝试这些表情符号时,表情符号总是出现在字母之前和数字之后。它们也出现在被视为文本的数字之前,即'0'1'2。标志出现在字母之后。因此,Excel确实将表情符号视为数字,但将它们实际数字之后排序。这是 Excel 特有的,可能是因为 Excel 使用此类字形作为仪表板中的指示符
  • 我尝试了更多表情符号,但 Excel 的顺序不是很一致,但它确实建议将表情符号视为“数字”。我发布了结果

标签: sql-server azure-sql-database collation


【解决方案1】:

在任何以表情符号开头的字符串之后排序aa-bb 是没有意义的。 ab 等 ASCII 字母在所有排序规则中排在首位。

表情符号不属于任何语言,因此一般的排序规则不会以任何特定方式对它们进行排序。您需要使用二进制排序规则而不是 (_BIN2),它根据字符的代码点值对字符进行排序。例如:

SELECT Val
FROM (VALUES
    (N'⭐⭐⭐'),
    (N'⭐⭐⭐'),
    (N'?'),
    (N'⭐⭐'),
    (N'⭐⭐'),
    (N'??'),
    (N'⭐'),
    (N'❗❗'),
    (N'❗❗'),
    (N'❗'),
    (N'❗'),
    (N'❗❗❗'),
    (N'❗❗❗'),
    (N'bb'),
    (N'αα'),
    (N'ab'),
    (N'aa')
) AS A (Val)
ORDER BY Val COLLATE Greek_BIN2;

ORDER BY Val COLLATE Latin1_General_100_BIN2;

生产

aa
ab
bb
αα
❗
❗
❗❗
❗❗
❗❗❗
❗❗❗
⭐
⭐⭐
⭐⭐
⭐⭐⭐
⭐⭐⭐
?
??

Excel 为何如此?

看起来 Excel 将这些字形视为数字,但将它们实际数字之后排序。带数字的文本也排在表情符号之后。

我怀疑表情符号被视为数字,因为 Excel 使用此类字形作为仪表板中的指示符。

虽然顺序不是很一致,但后来出现在 Unicode 表中的表情符号会排在星号和标志之前。在 Excel For Mac 中,按升序排序会生成此图像:

【讨论】:

  • 二进制排序规则实际上按代码点排序;忽略任何语言排序规则(比较 select * from (values (N'rôle'), (N'roles')) _(x) ORDER BY x COLLATE French_BIN2/French_CI_AS)。不同语言的二进制排序规则之间的区别在于它们还决定了字符串在[VAR]CHAR 类型中的存储方式,但是对于Unicode 类型,所有二进制排序规则几乎是等效的。 (几乎是因为它们仍然影响诸如小写和大写之类的东西,这可能因语言而异——但不是排序。)
  • @JeroenMostert 哎呀。
  • 我发现你说的两种排序规则都非常适合对表情符号字符进行排序。 Latin1_General_100_BIN2 也区分大小写和重音。 Greek_BIN2 区分大小写但不区分重音。我需要两者都不敏感,所以Greek_BIN2 是最适合我的情况的解决方案。
  • @gsubiran:Greek_BIN2 对重音不敏感。如果您使用的是 Unicode,则没有区别。如果您不使用 Unicode,您会得到不同的顺序,因为希腊语没有重音拉丁字符的编码(除其他外,特别是包括表情符号),因此这些会在 before 排序之前进行转换。这可能表面上看起来像是对口音不敏感,但这是完全不同的事情! Demo。依赖 SQL Server 如何转换不可表示的字符并不是一个好主意。
  • @gsubiran 我用Greek_BIN2 只是作为一个例子,当涉及到表情符号时,语言并不重要。任何_BIN2 的行为都应该相同*如果您使用Unicode。否则,您将根本无法存储表情符号。单字节代码页根本没有空间用于表情符号,并且表情符号几乎肯定会被 ? 替换。
【解决方案2】:

尝试二进制排序规则。 EG

SELECT Val
FROM (VALUES
    (N'⭐⭐⭐'),
    (N'⭐⭐⭐'),
    (N'?'),
    (N'⭐⭐'),
    (N'⭐⭐'),
    (N'??'),
    (N'⭐'),
    (N'❗❗'),
    (N'❗❗'),
    (N'❗'),
    (N'❗'),
    (N'❗❗❗'),
    (N'❗❗❗'),
    (N'bb'),
    (N'ab'),
    (N'aa')
) AS A (Val)
ORDER BY Val COLLATE Latin1_General_100_BIN2

输出

Val
----
aa
ab
bb
❗
❗
❗❗
❗❗
❗❗❗
❗❗❗
⭐
⭐⭐
⭐⭐
⭐⭐⭐
⭐⭐⭐
?
??

(16 rows affected)

【讨论】:

    猜你喜欢
    • 2016-02-02
    • 2015-07-29
    • 1970-01-01
    • 2018-03-20
    • 2012-11-07
    • 1970-01-01
    • 2015-02-24
    • 2023-03-17
    • 2019-02-27
    相关资源
    最近更新 更多