【问题标题】:Comparing strings in postgres using comparison operators?使用比较运算符比较postgres中的字符串?
【发布时间】:2017-03-28 19:59:20
【问题描述】:

在许多编程语言中,您可以使用 >、>=、

以 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 'a' &lt; 'b'; 在 postgres 9.6.1 中的结果为 True。 select '6.2(5a)' &lt; '6.2(5b)'; 返回 True。 select '6.2(15)' &lt; '6.2(5a)'; 也返回 True。最后一个是真的,因为6.2( 是匹配的。下一个字符'1' &lt; '5' 使 6.2(15) 小于 6.2(5a)。这不是你的期望吗?
  • 好吧,实际上这似乎是问题所在。后者比较 select '6.2(15)'

标签: postgresql natural-sort


【解决方案1】:

注意原来的答案是红鲱鱼

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

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 by 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

【讨论】:

  • 这是很好的信息,不幸的是,这是在 greenplum 中运行的 postgres,它是一个封闭的系统。我无法安装扩展程序。
  • @bakamike 我添加了一个使用存储过程的替代方案。
  • 新更新后 psql 将提供 select 'a'
  • @MichealToru select 'a' &lt; 'z'; 已经是真的了。你的意思是select 'a' &lt; 'Z';?哪个更新做出了改变?
  • @MichealToru 原来答案的前半部分是一条红鲱鱼。我已经把它去掉了。感谢您的来信。
猜你喜欢
  • 2012-10-05
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 2013-09-16
  • 2019-07-25
  • 2016-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多