web-dev-qa-db-ja.com

比較演算子を使用してpostgresの文字列を比較しますか?

多くのプログラミング言語では、>、> =、<などの演算子を使用して文字列を比較できます。言語は、アルファベットの文字の位置に基づいて比較を行います。

例えば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でこれにどう対処しますか?

7
bakamike

[〜#〜]ノート[〜#〜]赤いニシンで元の答えが出ました

単純な比較では、文字ごとに並べ替えられます。

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

...しかしすぐにポットに行きます。

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

必要なのは 自然ソート で、文字列の部分は文字列として比較され、数値は数値として比較されます。 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]+'), ''), 1, 12), 12, ' ') || btrsort(btrsort_nextunit($1))
            END
        ELSE
            $1
        END
      ;
$$ LANGUAGE SQL;

それは比較演算子を提供していませんが、私はそれを理解するふりをするつもりはありません。これにより、order by

select * from things order by btrsort(whatever);

自然にソートされたクエリが大きなテーブルで泥に変わるのを防ぐために、 その関数の結果にbtreeインデックスを作成できます

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

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

これは、テーブルが空の場合のみ何も出力しません。 selectステートメントをテストするためにテーブルは必要ありません。

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