如何在 DELETE 查询中将 postgres 函数结果用作单独的列

How to use postgres function result as a separate column in DELETE query

我必须根据与其中一列上的超长函数应用程序的多重比较来删除 table 中的行。详细一点,我从 base64 解码,做一个子字符串,转换为 json,获取特定字段,然后将其转换为 inet

我正在使用这些 ips 与我的 WHERE 子句中的其他 ips/掩码进行比较。

我遇到的问题是获得实际结果是一个很长的字符串,如果我最后说 ip < foo(bar(baz(quux))) OR ip2 < foo(bar(baz(quux))) 那么用于比较的值最终也会被计算多次。

我正在寻找一种方法来预先计算该值,为其分配一个有意义的名称,然后在我的 WHERE 子句中使用该名称。

谢谢

您可以使用横向连接:

select . . .
from t cross join lateral
     (values (foo(bar(baz(quux))) ) v(decoded_value)
where ip < v.decoded_vaue or ip2 < v.decoded_value;

在 Postgres 中,delete 有点棘手。假设你有一个主键:

delete t
using t t2 cross join lateral
     (values (foo(bar(baz(t2.quux))) ) v(decoded_value)
where t2.primary_key = t.primary_key and
      (t2.ip < v.decoded_vaue or t2.ip2 < v.decoded_value);

您是否考虑过 CTE 的用法?

例如,假设我们有以下 table

CREATE TABLE test_table (
  id BIGINT PRIMARY KEY,
  some_data INTEGER
);

假设我们要删除表达式结果为

的所有行

some_data % 10

是(>=1 且 <=4)或(>=6 且 <=8)。

在这种情况下,模运算会用模运算替换您的 foo(bar(baz(column_name))) 调用。

简单的方法是编写以下查询:

DELETE FROM test_table
WHERE
  (MOD(some_data, 10) >= 1 AND MOD(some_data, 10) <= 4)
  OR
  (MOD(some_data, 10) >=6 AND MOD(some_data, 10) <= 8);

如您所说,这将多次重新计算同一件事。为了只计算一次,我们可以创建一个CTE并在删除查询中使用结果。

WITH precalculated_table AS (
  SELECT *, mod(some_data, 10) as mod_10_result FROM test_table
)
DELETE FROM test_table WHERE id IN (
    SELECT id from precalculated_table
  where
    (mod_10_result >= 1 and mod_10_result <= 4)
    OR
    (mod_10_result >= 6 AND mod_10_result <= 8)
);

这样,我们只计算一次,然后在 DELETE 查询的 WHERE 部分使用预先计算的列。