首页 > 解决方案 > 使用 node 和 pg-promise 加入 postgres 中的值列表

问题描述

我正在尝试创建一个查询,例如

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 标记的数组,它会在值之前添加“数组”,然后出现语法错误。

标签: node.jspostgresqlpg-promise

解决方案


鉴于我有一个数组,其中包含数组中的数字 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;

推荐阅读