PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Penyortiran angka manusiawi atau alami dari string kata-dan-angka campuran

Membangun data pengujian Anda, tetapi ini berfungsi dengan data arbitrer. Ini bekerja dengan sejumlah elemen dalam string.

Daftarkan jenis komposit yang terdiri dari satu text dan satu integer nilai sekali per database. Saya menyebutnya ai :

CREATE TYPE ai AS (a text, i int);

Caranya adalah dengan membentuk array ai dari setiap nilai dalam kolom.

regexp_matches() dengan pola (\D*)(\d*) dan g opsi mengembalikan satu baris untuk setiap kombinasi huruf dan angka. Ditambah satu baris menjuntai yang tidak relevan dengan dua string kosong '{"",""}' Memfilter atau menekannya hanya akan menambah biaya. Gabungkan ini ke dalam array, setelah mengganti string kosong ('' ) dengan 0 dalam integer komponen (sebagai '' tidak dapat dilemparkan ke integer ).

NULL nilai urutkan terlebih dahulu - atau Anda harus membuat huruf besar-kecil - atau gunakan seluruh Shebang dalam STRICT berfungsi seperti yang diusulkan @Craig.

Postgres 9.4 atau lebih baru

SELECT data
FROM   alnum
ORDER  BY ARRAY(SELECT ROW(x[1], CASE x[2] WHEN '' THEN '0' ELSE x[2] END)::ai
                FROM regexp_matches(data, '(\D*)(\d*)', 'g') x)
        , data;

db<>main biola di sini

Postgres 9.1 (jawaban asli)

Diuji dengan PostgreSQL 9.1.5, di mana regexp_replace() memiliki perilaku yang sedikit berbeda.

SELECT data
FROM  (
    SELECT ctid, data, regexp_matches(data, '(\D*)(\d*)', 'g') AS x
    FROM   alnum
    ) x
GROUP  BY ctid, data   -- ctid as stand-in for a missing pk
ORDER  BY regexp_replace (left(data, 1), '[0-9]', '0')
        , array_agg(ROW(x[1], CASE x[2] WHEN '' THEN '0' ELSE x[2] END)::ai)
        , data         -- for special case of trailing 0

Tambahkan regexp_replace (left(data, 1), '[1-9]', '0') sebagai ORDER BY pertama item untuk menangani digit utama dan string kosong.

Jika karakter khusus seperti {}()"', dapat terjadi, Anda harus menghindarinya.
Saran @Craig untuk menggunakan ROW ekspresi menangani itu.

BTW, ini tidak akan dijalankan di sqlfiddle, tetapi bisa di cluster db saya. JDBC tidak sanggup. sqlfiddle mengeluh:

Metode org.postgresql.jdbc3.Jdbc3Array.getArrayImpl(long,int,Map) belum diterapkan.

Ini telah diperbaiki:http://sqlfiddle.com/#!17/fad6e/1



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Pencadangan &Pemulihan PostgreSQL 9.0

  2. postgres kueri dinamis

  3. pemilik database postgresql tidak dapat mengakses database - Tidak ada hubungan yang ditemukan.

  4. PostgreSQL:menggunakan kolom terhitung dalam kueri yang sama

  5. Bagaimana pg_sleep_for() Bekerja di PostgreSQL