web-dev-qa-db-ja.com

postgresでの英数字の大文字と小文字を区別しないソート

Postrgesは初めてで、varchar型の列を並べ替えたいと思っています。以下の例で問題を説明したい:

テーブル名:testsorting

   order       name
    1            b
    2            B
    3            a
    4            a1
    5            a11
    6            a2
    7            a20
    8            A
    9            a19

大文字と小文字を区別する並べ替え(postgresではデフォルト)は次のようになります:

select name from testsorting order by name;

    A
    B
    a
    a1
    a11
    a19
    a2
    a20
    b

大文字と小文字を区別しない並べ替えでは次のようになります:

uPPER(name);によるテストソート順から名前を選択します。

      A
      a
      a1
      a11
      a19
      a2
      a20
      B
      b

postgresで英数字の大文字と小文字を区別しない並べ替えを行って順序を下回るにはどうすればよいですか

          a
          A
          a1
          a2
          a11
          a19
          a20
          b
          B

大文字または小文字の順序は気になりませんが、順序は「aAbB」または「AaBb」であり、「ABab」であってはなりません。

Postgresでこれに対する解決策があるかどうか提案してください。

18
akhi

私のPostgreSQLはあなたが望むようにソートします。 PostgreSQLが文字列を比較する方法は、ロケールと照合順序によって決まります。 createdbを使用してデータベースを作成する場合、ロケールを設定するための-lオプションがあります。また、psql -lを使用して、環境でどのように構成されているかを確認できます。

[postgres@test]$ psql -l
List of databases
 Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
---------+----------+----------+------------+------------+-----------------------
 mn_test | postgres | UTF8     | pl_PL.UTF8 | pl_PL.UTF8 |

ご覧のとおり、私のデータベースはポーランド語の照合を使用しています。

他の照合順序を使用してデータベースを作成した場合は、次のようにクエリで他の照合順序を使用できます。

SELECT * FROM sort_test ORDER BY name COLLATE "C";
SELECT * FROM sort_test ORDER BY name COLLATE "default";
SELECT * FROM sort_test ORDER BY name COLLATE "pl_PL";

次の方法で利用可能な照合順序を一覧表示できます。

SELECT * FROM pg_collation;

編集済み:

ああ、「a11」が「a2」の前にあるに違いないことを見逃しました。

標準の照合で英数字の並べ替えを解決できるとは思いません。このような並べ替えでは、Clodoaldo Netoの応答と同様に、文字列をパーツに分割する必要があります。この方法で頻繁に注文する必要がある場合に役立つもう1つのオプションは、名前フィールドを2つの列に分割することです。 INSERTとUPDATEで、namename_1name_2に分割するトリガーを作成してから次のことを行うことができます。

SELECT name FROM sort_test ORDER BY name_1 COLLATE "en_EN", name_2;

(照合順序をポーランド語から英語に変更しました。ネイティブ照合順序を使用して、aącćなどの文字を並べ替える必要があります)

7
Michał Niklas

名前が常に1 alpha followed by n numerics形式の場合、次のようになります。

select name
from testsorting
order by
    upper(left(name, 1)),
    (substring(name from 2) || '0')::integer
5
Clodoaldo Neto

これ から強くインスピレーションを得た回答。
関数を使用すると、さまざまなクエリで必要になった場合に、関数をクリーンに保つことが簡単になります。

CREATE OR REPLACE FUNCTION alphanum(str anyelement)
   RETURNS anyelement AS $$
BEGIN
   RETURN (SUBSTRING(str, '^[^0-9]*'),
      COALESCE(SUBSTRING(str, '[0-9]+')::INT, -1) + 2000000);
END;
$$ LANGUAGE plpgsql IMMUTABLE;

次に、次のように使用できます。

SELECT name FROM testsorting ORDER BY alphanum(name);

テスト:

WITH x(name) AS (VALUES ('b'), ('B'), ('a'), ('a1'),
   ('a11'), ('a2'), ('a20'), ('A'), ('a19'))
SELECT name, alphanum(name) FROM x ORDER BY alphanum(name);

 name |  alphanum   
------+-------------
 a    | (a,1999999)
 A    | (A,1999999)
 a1   | (a,2000001)
 a2   | (a,2000002)
 a11  | (a,2000011)
 a19  | (a,2000019)
 a20  | (a,2000020)
 b    | (b,1999999)
 B    | (B,1999999)
0
Le Droid

PostgreSQLは、Cライブラリロケール機能を使用して文字列を並べ替えます。 Cライブラリは、ホストオペレーティングシステムによって提供されます。 Mac OS XまたはBSDファミリのオペレーティングシステムでは、UTF-8ロケール定義が壊れているため、結果は照合順序「C」のとおりです。

ホストOSとしてubuntu 15.04を使用した照合結果用に添付された画像

詳細については、postgres wikiのFAQを確認してください: https://wiki.postgresql.org/wiki/FAQ

0
Manu Singhal

私に関する限り、私はPostgreSQLモジュールcitextを使用し、CITEXTの代わりにデータ型TEXTを使用しました。これらの列での並べ替えと検索の両方で大文字と小文字が区別されなくなります。

モジュールはSQLコマンドCREATE EXTENSION IF NOT EXISTS citext;でインストールできます

0
Alexis.Rolland