PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Sắp xếp nhân bản hoặc số tự nhiên của các chuỗi từ và số hỗn hợp

Xây dựng dựa trên dữ liệu thử nghiệm của bạn, nhưng điều này hoạt động với dữ liệu tùy ý. Điều này hoạt động với bất kỳ số phần tử nào trong chuỗi.

Đăng ký một kiểu kết hợp được tạo thành từ một text và một integer giá trị một lần cho mỗi cơ sở dữ liệu. Tôi gọi nó là ai :

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

Bí quyết là tạo một mảng ai từ mỗi giá trị trong cột.

regexp_matches() với mẫu (\D*)(\d*)g tùy chọn trả về một hàng cho mọi kết hợp chữ cái và số. Cộng với một hàng lủng lẳng không liên quan với hai chuỗi trống '{"",""}' Việc lọc hoặc loại bỏ nó sẽ chỉ làm tăng thêm chi phí. Tổng hợp giá trị này thành một mảng, sau khi thay thế các chuỗi trống ('' ) với 0 trong integer thành phần (dưới dạng '' không thể chuyển thành integer ).

NULL các giá trị sắp xếp trước - hoặc bạn phải viết hoa chữ thường đặc biệt - hoặc sử dụng toàn bộ trong một STRICT chức năng như @Craig đề xuất.

Postgres 9.4 trở lên

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 <> fiddle here

Postgres 9.1 (câu trả lời gốc)

Đã kiểm tra với PostgreSQL 9.1.5, trong đó regexp_replace() có một hành vi hơi khác.

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

Thêm regexp_replace (left(data, 1), '[1-9]', '0') dưới dạng ORDER BY đầu tiên mục để quan tâm đến các chữ số đứng đầu và chuỗi trống.

Nếu các ký tự đặc biệt như {}()"', có thể xảy ra, bạn phải thoát khỏi những điều đó cho phù hợp. Đề xuất của
@ Craig để sử dụng ROW biểu thức đảm nhận điều đó.

BTW, điều này sẽ không thực thi trong sqlfiddle, nhưng nó thực hiện trong cụm db của tôi. JDBC không phụ thuộc vào nó. sqlfiddle phàn nàn:

Phương thức org.postgresql.jdbc3.Jdbc3Array.getArrayImpl (long, int, Map) chưa được triển khai.

Điều này đã được khắc phục sau đó: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. Liệt kê các hàm được lưu trữ tham chiếu đến một bảng trong PostgreSQL

  2. Làm cách nào để tự động cập nhật dấu thời gian trong PostgreSQL

  3. Trường mô hình duy nhất trong Django và phân biệt chữ hoa chữ thường (postgres)

  4. SQLAlchemy không có mật khẩu được cung cấp lỗi

  5. Báo cáo xu hướng PostgreSQL 2019:Đám mây riêng và đám mây công cộng, Di chuyển, Kết hợp cơ sở dữ liệu &Lý do hàng đầu được sử dụng