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
объединении:
Postgres 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;