23

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(名前) によるテスト並べ替え順序から名前を選択します。

      A
      a
      a1
      a11
      a19
      a2
      a20
      B
      b

postgres で英数字の大文字と小文字を区別しない並べ替えを行うにはどうすればよいですか?

          a
          A
          a1
          a2
          a11
          a19
          a20
          b
          B

大文字、小文字の順番は気にしませんが、「aAbB」か「AaBb」で、「ABab」ではいけません。

postgresでこれに対する解決策があれば提案してください。

4

6 に答える 6

10

私の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」の前にあるに違いないことを見逃しました。

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

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

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

于 2013-03-15T09:16:31.720 に答える
5

名前が常に次の1 alpha followed by n numerics形式の場合:

select name
from testsorting
order by
    upper(left(name, 1)),
    (substring(name from 2) || '0')::integer
于 2013-03-15T11:24:20.053 に答える
0

Clodoaldo Netoの回答に同意しますが、インデックスを追加することも忘れないでください

CREATE INDEX testsorting_name on testsorting(upper(left(name,1)), substring(name from 2)::integer)
于 2013-03-17T05:45:28.857 に答える
0

this oneから強くインスピレーションを得て答えてください。
関数を使用すると、さまざまなクエリで必要な場合に、関数をきれいに保つのが簡単になります。

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)
于 2016-07-06T22:48:55.473 に答える