WITH ORDINALITY
у Postgres 9.4 або пізнішої версії
Нова функція спрощує цей клас проблем. Наведений вище запит тепер може бути просто:
SELECT *
FROM regexp_split_to_table('I think Postgres is nifty', ' ') WITH ORDINALITY x(word, rn);
Або застосовано до таблиці:
SELECT *
FROM tbl t, regexp_split_to_table(t.my_column, ' ') WITH ORDINALITY x(word, rn);
Деталі:
Про неявне LATERAL
приєднання:
Постгреси 9.3 або старші - і більш загальне пояснення
Для однієї струни
Ви можете застосувати функцію вікна, row_number()
щоб запам'ятати порядок елементів. Однак зі звичайними row_number() OVER (ORDER BY col)
ви отримуєте числа відповідно до порядку сортування , а не вихідного положення в рядку.
Ви можете просто пропустити ORDER BY
позицію "як є":
SELECT *, row_number() OVER () AS rn
FROM regexp_split_to_table('I think Postgres is nifty', ' ') AS x(word);
Виконання regexp_split_to_table()
деградів з довгими струнами. unnest(string_to_array(...))
ваги краще:
SELECT *, row_number() OVER () AS rn
FROM unnest(string_to_array('I think Postgres is nifty', ' ')) AS x(word);
Однак, хоча це нормально працює, і я ніколи не бачив, щоб він порушувався у простих запитах, Postgres не стверджує нічого про порядок рядків без явного ORDER BY
.
Щоб гарантувати порядкові номери елементів у вихідному рядку, використовуйте generate_subscript()
(покращене коментарем @deszo):
SELECT arr[rn] AS word, rn
FROM (
SELECT *, generate_subscripts(arr, 1) AS rn
FROM string_to_array('I think Postgres is nifty', ' ') AS x(arr)
) y;
Для таблиці рядків
Додати PARTITION BY id
до OVER
пункту ...
Демонстраційна таблиця:
CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
('I think Postgres is nifty')
,('And it keeps getting better');
Я використовую ctid
як спеціальний замінник первинного ключа . Якщо у вас є один (або будь-який унікальний стовпець ), використовуйте це замість цього.
SELECT *, row_number() OVER (PARTITION BY ctid) AS rn
FROM (
SELECT ctid, unnest(string_to_array(string, ' ')) AS word
FROM strings
) x;
Це працює без чіткого ідентифікатора:
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;
SQL Fiddle.
Відповідь на запитання
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;