объединение списка значений в postgres с использованием node и pg-обещания - PullRequest
1 голос
/ 04 апреля 2019

Я пытаюсь создать запрос, например

SELECT e.col1, e.col2 
FROM entity e
INNER JOIN (
    VALUES
    (1377776),(1377792),(1377793),(1377794),(1377795),(1377796)
) ex(ex_entityid) ON (entityid = ex_entityid)

Учитывая, что у меня есть массив, содержащий числа 13777xx в массиве, как мне сгенерировать этот запрос?

Я получил этот синтаксис из этого вопроса: https://stackoverflow.com/a/17824797/425544. Мой список ввода достаточно большой, чтобы использовать IN слишком медленно.

Пока что, используя $ 0: csv, я могу получить мои значения в виде списка через запятую. Я не знаю, как форматировать значения так, чтобы вокруг него были круглые скобки. Если я даю массив без тега: csv, он добавляет «массив» перед значениями, а затем я получаю синтаксическую ошибку.

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

Это нестандартный формат, поэтому вам нужно использовать Форматирование нестандартного типа :

const wrap = arr => ({
    rawType: true,
    toPostgres: () => arr.map(a => pgp.as.format('($1)', [a])).join()
});

Теперь вы можете использовать такой обернутый массив как простую переменную форматирования:

const data = [1377776, 1377792, 1377793];
db.any('... INNER JOIN (VALUES $1)', [wrap(data)]);
1 голос
/ 05 апреля 2019

Учитывая, что у меня есть массив, содержащий числа 13777xx в массиве, как мне сгенерировать этот запрос?

Произвольные числа

Если у вас есть фактический массив , просто передайте литерал массива в виде:

'{1377776,1377792,1377793}'

Для небольших массивов, в которых имеется всего несколько значений, вы можете просто использовать конструкцию ANY в соединении:

SELECT col1, col2 
FROM   entity
WHERE  entityid = ANY ($my_array::int[]);

Для строкового литерала вам понадобится явное приведение типа, как показано.

Для длинных массивов будет более эффективно развернуть массив в набор (производную таблицу), а затем соединить , как прокомментировал mu :

SELECT col1, col2
FROM   unnest(my_array::int[]) ex(entityid)
JOIN   entity USING (entityid);

С соответствующим именем столбца для неопубликованных чисел вы можете удобно использовать короткое предложение USING для условия соединения.

Обратите внимание на небольшую разницу: первый запрос неявно складывает дубликаты во входных данных, а второй с объединением создает дубликаты для дубликатов во входных данных. Ваш выбор.

В качестве альтернативы вы также можете передать отдельные значения в выражение IN. Но это обычно медленнее. (Опять же: складывает дубликаты.) Как:

...
WHERE  entityid IN (1377776, 1377792, 1377793);

См:

Для повторных операций вы можете создать функцию VARIADIC и передать отдельные числа в качестве параметров (или литерал одного массива, по вашему выбору). См:

Не очень произвольные числа

Если вы действительно хотите, чтобы ваш запрос основывался на "числах 13777xx" , что означает все числа от 1377700 до 1377799, используйте вместо этого generate_series(). Как:

SELECT col1, col2 
FROM   generate_series(1377700, 1377799) entityid
JOIN   entity USING (entityid);

Или, самое простое и быстрое, адаптировать предложение WHERE с предикатом одного диапазона:

SELECT col1, col2 
FROM   entity
WHERE  entityid BETWEEN 1377700 AND 1377799;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...