WITH ORDINALITY
trong Postgres 9,4 trở lên
Tính năng mới đơn giản hóa lớp vấn đề này. Truy vấn trên có thể chỉ đơn giản là:
SELECT *
FROM regexp_split_to_table('I think postgres is nifty', ' ') WITH ORDINALITY x(word, rn);
Hoặc, áp dụng cho bảng:
SELECT *
FROM tbl t, regexp_split_to_table(t.my_column, ' ') WITH ORDINALITY x(word, rn);
Chi tiết:
Về việc LATERAL
tham gia ngầm :
Postgres 9.3 trở lên - và giải thích tổng quát hơn
Đối với một chuỗi
Bạn có thể áp dụng chức năng cửa sổ row_number()
để ghi nhớ thứ tự các phần tử. Tuy nhiên, với thông thường, row_number() OVER (ORDER BY col)
bạn nhận được các số theo thứ tự sắp xếp , không phải vị trí ban đầu trong chuỗi.
Bạn có thể thử và chỉ cần bỏ qua ORDER BY
để có được vị trí "như hiện tại":
SELECT *, row_number() OVER () AS rn
FROM (
SELECT regexp_split_to_table('I think postgres is nifty', ' ') AS word
) x;
Hiệu suất của regexp_split_to_table()
suy thoái với chuỗi dài. unnest(string_to_array(...))
cân tốt hơn:
SELECT *, row_number() OVER () AS rn
FROM (
SELECT unnest(string_to_array('I think postgres is nifty', ' ')) AS word
) x;
Tuy nhiên, trong khi điều này thường hoạt động và tôi chưa bao giờ thấy nó bị hỏng trong các truy vấn đơn giản, PostgreQuery khẳng định không có gì về thứ tự của các hàng mà không có một điều rõ ràng ORDER BY
.
Để đảm bảo số thứ tự của các phần tử trong chuỗi gốc, hãy sử dụng generate_subscript()
(được cải thiện với nhận xét của @deszo):
SELECT arr[rn] AS word, rn
FROM (
SELECT *, generate_subscripts(arr, 1) AS rn
FROM (
SELECT string_to_array('I think postgres is nifty', ' ') AS arr
) x
) y;
Đối với một bảng chuỗi
Thêm PARTITION BY id
vào OVER
mệnh đề ...
Bảng demo:
CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
('I think postgres is nifty')
,('And it keeps getting better');
Tôi sử dụng ctid
như là một thay thế ad-hoc cho một khóa chính . Nếu bạn có một (hoặc bất kỳ cột duy nhất ), hãy sử dụng thay thế.
SELECT *, row_number() OVER (PARTITION BY ctid) AS rn
FROM (
SELECT ctid, unnest(string_to_array(string, ' ')) AS word
FROM strings
) x;
Điều này hoạt động mà không có bất kỳ ID riêng biệt:
SELECT arr[rn] AS word, rn
FROM (
SELECT *, generate_subscripts(arr, 1) AS rn
FROM (
SELECT string_to_array(string, ' ') AS arr
FROM strings
) x
) y;
Câu đố SQL.
Trả lời câu hỏi
SELECT z.arr, z.rn, z.word, d.meaning -- , partofspeech -- ?
FROM (
SELECT *, arr[rn] AS word
FROM (
SELECT *, generate_subscripts(arr, 1) AS rn
FROM (
SELECT string_to_array(string, ' ') AS arr
FROM strings
) x
) y
) z
JOIN dictionary d ON d.wordname = z.word
ORDER BY z.arr, z.rn;