加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql – 使用比较运算符比较postgres中的字符串?

发布时间:2020-12-13 16:05:17 所属栏目:百科 来源:网络整理
导读:在许多编程语言中,您可以使用, =,等运算符来比较字符串.等...语言将基于字母表中字母的位置进行比较. 例如在 PHP中 if ('a' 'b') { echo 'Yes';} else { echo 'No';} Yes 但是在postgres或mysql中 SELECTCASE WHEN 'a' 'b' THEN 'yes' ENDFROM tableOutput:
在许多编程语言中,您可以使用>,> =,<等运算符来比较字符串.等...语言将基于字母表中字母的位置进行比较. 例如在 PHP中

if ('a' < 'b') {
    echo 'Yes';
} else {
    echo 'No';
}
> Yes

但是在postgres或mysql中

SELECT
CASE WHEN 'a' < 'b' THEN 'yes' END
FROM table
Output: null

我有一个包含字符串的表,我需要通过SQL相互比较.

例如:
6.2(??5a)中
6.2(??5b) – 这将大于6.2(5a)
要么
6.2(??15) – 这将大于6.2(5a)

我想过使用正则表达式给一个字母分配一个数字,但是当没有字母时,这会打破比较.

你会如何在SQL中纯粹地解决这个问题?

解决方法

大多数字符串比较默认为所谓的 ASCIIbetical sorting.它将每个字符转换为其ASCII编号(或者可能是UTF-8,其与前7位的ASCII重叠)然后进行排序.这看起来很好……

select 'a' < 'z'; -- true

……但很快就会出错.

select 'a' < 'Z'; -- false

这是因为所有大写字母都在ASCII和UTF-8中的所有小写字母之后.

解决这个问题的简单方法是通过在两侧调用upper或lower来规范化大小写.

select lower('a') < lower('Z'); -- true

ASCIIbetical排序的第二个问题是数字.再次,它开始很好……

select 'a9' < 'a1'; -- true

……但很快就去了锅.

select 'a9' < 'a10'; -- false

ASCIIbetical排序一次比较一个字符. ASCII 9(57)小于ASCII 1(49).

你想要的是一个natural sort,其中字符串部分作为字符串进行比较,数字作为数字进行比较.在SQL中进行自然排序并不是最简单的事情.您需要固定的字段宽度来分别对每个子字符串进行排序,或者可能需要使用正则表达式…

幸运的是,pg_natural_sort_order是Postgres扩展,实现了高效的自然排序.

如果您无法安装扩展,则可以使用存储过程,例如2kan的btrsort.

CREATE FUNCTION btrsort_nextunit(text) RETURNS text AS $$
    SELECT 
        CASE WHEN $1 ~ '^[^0-9]+' THEN
            COALESCE( SUBSTR( $1,LENGTH(SUBSTRING($1 FROM '[^0-9]+'))+1 ),'' )
        ELSE
            COALESCE( SUBSTR( $1,LENGTH(SUBSTRING($1 FROM '[0-9]+'))+1 ),'' )
        END

$$LANGUAGE SQL;

CREATE FUNCTION btrsort(text) RETURNS text AS $$
    SELECT 
        CASE WHEN char_length($1)>0 THEN
            CASE WHEN $1 ~ '^[^0-9]+' THEN
                RPAD(SUBSTR(COALESCE(SUBSTRING($1 FROM '^[^0-9]+'),''),1,12),12,' ') || btrsort(btrsort_nextunit($1))
            ELSE
                LPAD(SUBSTR(COALESCE(SUBSTRING($1 FROM '^[0-9]+'),' ') || btrsort(btrsort_nextunit($1))
            END
        ELSE
            $1
        END
      ;
$$LANGUAGE SQL;

虽然它没有提供比较运算符,但我不会假装理解它.这允许您按顺序使用它.

select * from things order by btrsort(whatever);

为防止自然排序的查询在大型桌子上变成泥,you can create a btree index on the result of that function.

create index things_whatever_btrsort_idx ON things( btrsort(whatever) );

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读