我想在桌面上输入一系列字符串。 例如
Chapter 1
Chapter 2
Chapter 11
Chapter 12
要正确订购,我需要用零填充它们。
Chapter 001
Chapter 002
Chapter 011
Chapter 012
也许我可以使用正则表达式在零中使用 regexp_replace()
pad。
regexp_replace(chapters.name,'(\d+)\D*','0\1') as name
此解决方案无效。我想也许我可以弄清楚反向引用的长度并使用该数字填充我需要的东西:
regexp_replace(chapters.name,'(\d+)\D*',lpad('\l',3-length('\1'),'0') as name
但\1
中的length()
始终返回2,即使我注意到在某些postgres函数\1
中使用\1
将{{1}}转换为实际捕获的数据。
如何使用Postgres字符串函数和Postgres正则表达式填充零?
答案 0 :(得分:5)
你的第二次尝试是两个误解的受害者:
您将regexp_replace()
的范围与lpad()
的范围混淆。 lpad()
首先执行,\l
和\1
对lpad()
没有特殊含义。
这是“自然排序”的问题。相关回答:
正如那里所建议的那样,最好的解决方案是存储标准化数据。如果前导'Chapter'实际上是所有值中的不可变字符串,请不要存储它,只将数字部分存储为integer
。
如果您的示例值是准确的,我们可以忽略前导常量文本,只按尾随数字排序。比任何重新格式化字符串的尝试要快得多:
SELECT *
FROM chapters
ORDER BY split_part(name, ' ', 2)::int
如果您确实需要零填充字符串,并且前导文本可能会有所不同:
SELECT split_part(name, ' ', 1) || ' '
|| lpad(split_part(name, ' ', 2), 3, '0')
FROM chapters
ORDER BY 1;
两个函数调用加上连接,但仍然比regexp_replace()
快。正则表达式相对昂贵
lpad()
的更多示例: