将 table 与 Postgres 中的数组进行比较
Compare table with array in Postgres
我需要将我的数组与 table 进行比较。
我需要知道数组中存在哪些代码而 table 中缺少哪些代码。
以及 table 中存在哪些代码而数组中缺少这些代码。
我正在使用 Node+KnexJS+PostgreSQL:
const myArray = `array['10001517','1509','1524','155400X','903B','910','1009201X']`
let divergence = await app.db.raw(`
select file, t.code as acc_missing
from unnest(${myArray}) file full join
table_a as t
on t.code LIKE file
where t.code is null or file is NULL
AND t.version LIKE '010'
AND t.inst = 300
`)
const errorDivergence = divergence.rows
我当前的查询执行此操作,但生成以下错误:
(node:26060) UnhandledPromiseRejectionWarning:
error: FULL JOIN is only supported with merge-joinable or hash-joinable join conditions
如错误消息所述,Postgres 仅支持 FULL [OUTER] JOIN
的连接条件,可用于合并连接或散列连接。 t.code LIKE file
不符合条件。
这是一个已知的限制。对于这种罕见的情况,人们还没有足够的兴趣来推动修复。参见:
但是,您的问题中没有任何内容表明您实际上需要 LIKE
:
I need to know which codes exist in the array and are missing from the table. As well as which codes exist in the table and are missing from the array.
这表示相等 (=
) - 效果很好:
SELECT file, t.code AS acc_missing
FROM unnest('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[]) file
FULL join table_a t ON t.code = file -- !
WHERE t.code IS NULL
OR file IS NULL AND t.version LIKE '010' AND t.inst = 300;
您设置查询格式的方式表明您需要在 (t.code IS NULL OR file IS NULL)
周围加上括号。 AND
在 OR
之前绑定。 The manual about operator precedence.
OTOH,添加的谓词 AND t.version LIKE '010' AND t.inst = 300
只有在没有括号的情况下才有意义。因此,这是使用 LEFT
& RIGHT JOIN
:
实现原始查询的解决方法
SELECT file, t.code AS acc_missing
FROM unnest('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[]) file
LEFT JOIN table_a t ON t.code LIKE file
WHERE t.code IS NULL
UNION ALL
SELECT file, t.code AS acc_missing
FROM unnest('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[]) file
RIGHT JOIN table_a t ON t.code LIKE file
WHERE file IS NULL AND t.version LIKE '010' AND t.inst = 300;
或者:
SELECT file, t.code AS acc_missing
FROM unnest('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[]) file
LEFT JOIN table_a t ON t.code LIKE file
WHERE t.code IS NULL
UNION ALL
SELECT NULL, t.code
FROM table_a t
WHERE (t.code LIKE ANY ('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[])) IS NOT TRUE;
db<>fiddle here
我需要将我的数组与 table 进行比较。
我需要知道数组中存在哪些代码而 table 中缺少哪些代码。 以及 table 中存在哪些代码而数组中缺少这些代码。
我正在使用 Node+KnexJS+PostgreSQL:
const myArray = `array['10001517','1509','1524','155400X','903B','910','1009201X']`
let divergence = await app.db.raw(`
select file, t.code as acc_missing
from unnest(${myArray}) file full join
table_a as t
on t.code LIKE file
where t.code is null or file is NULL
AND t.version LIKE '010'
AND t.inst = 300
`)
const errorDivergence = divergence.rows
我当前的查询执行此操作,但生成以下错误:
(node:26060) UnhandledPromiseRejectionWarning: error: FULL JOIN is only supported with merge-joinable or hash-joinable join conditions
如错误消息所述,Postgres 仅支持 FULL [OUTER] JOIN
的连接条件,可用于合并连接或散列连接。 t.code LIKE file
不符合条件。
这是一个已知的限制。对于这种罕见的情况,人们还没有足够的兴趣来推动修复。参见:
但是,您的问题中没有任何内容表明您实际上需要 LIKE
:
I need to know which codes exist in the array and are missing from the table. As well as which codes exist in the table and are missing from the array.
这表示相等 (=
) - 效果很好:
SELECT file, t.code AS acc_missing
FROM unnest('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[]) file
FULL join table_a t ON t.code = file -- !
WHERE t.code IS NULL
OR file IS NULL AND t.version LIKE '010' AND t.inst = 300;
您设置查询格式的方式表明您需要在 (t.code IS NULL OR file IS NULL)
周围加上括号。 AND
在 OR
之前绑定。 The manual about operator precedence.
OTOH,添加的谓词 AND t.version LIKE '010' AND t.inst = 300
只有在没有括号的情况下才有意义。因此,这是使用 LEFT
& RIGHT JOIN
:
SELECT file, t.code AS acc_missing
FROM unnest('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[]) file
LEFT JOIN table_a t ON t.code LIKE file
WHERE t.code IS NULL
UNION ALL
SELECT file, t.code AS acc_missing
FROM unnest('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[]) file
RIGHT JOIN table_a t ON t.code LIKE file
WHERE file IS NULL AND t.version LIKE '010' AND t.inst = 300;
或者:
SELECT file, t.code AS acc_missing
FROM unnest('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[]) file
LEFT JOIN table_a t ON t.code LIKE file
WHERE t.code IS NULL
UNION ALL
SELECT NULL, t.code
FROM table_a t
WHERE (t.code LIKE ANY ('{10001517,1509,1524,155400X,903B,910,1009201X}'::text[])) IS NOT TRUE;
db<>fiddle here