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

标签 postgresql natural-sort

在许多编程语言中,您可以使用 >、>=、< 等运算符比较字符串,并且该语言将根据字母在字母表中的位置进行比较。

例如在 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 来解决这个问题?

最佳答案

注意:原来的答案是转移注意力

一个简单的比较,一个字符一个字符地排序。

select 'a1' < 'a9'; -- true because 'a' = 'a' and '1' < '9'.

...但很快就去了底池。

select 'a10' < 'a9'; -- also true for the same reason.

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

幸运的是有 pg_natural_sort_order ,一个实现高效自然排序的 Postgres 扩展。

如果您无法安装扩展程序,您可以使用类似 btrsort 的存储过程由 2kan 提供。

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]+'), ''), 1, 12), 12, ' ') || btrsort(btrsort_nextunit($1))
            END
        ELSE
            $1
        END
      ;
$$ LANGUAGE SQL;

虽然它没有提供比较运算符,但我不会假装理解它。这允许您在 order by 中使用它。

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) );

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

如果表格为空,这只会输出任何内容。您不需要表格来测试选择语句。

SELECT
CASE WHEN 'a' < 'b' THEN 'yes' END  -- yes

关于postgresql - 使用比较运算符比较 postgres 中的字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40601324/

相关文章:

sql - 以类似 Excel 的方式在 MySQL 中对 varchar 列进行排序

r - 如何在 R 中执行自然(词典)排序?

c++ - 如何在 C++ 中实现自然排序算法?

python - 自然地对列表进行排序,将字母数字值移动到末尾

postgresql - 使用 PostgreSQL 的 Grails 中 hasMany 的奇怪问题。 "ERROR: column <column_name> does not exist"

sql - 如何让 Redshift/Postgresql LAG 窗口函数有选择地排除记录?

postgresql - 使用Docker Compose Psql进行Knex迁移

python - 如何对具有负数和字符的字符串进行自然排序?

sql - 如何使用三张表JOIN更新

sql - 对相关表的约束