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

问题描述 投票:1回答:2

我必须删除表中的行,这是基于与其中一列上的一个非常长的函数应用程序的多次比较。为了详细介绍,我正在从base64解码,做一个子串,转换为json,取一个特定的字段,然后将其转换为inet

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

我遇到的问题是获得实际结果是一个相当长的字符串,如果我最终说ip < foo(bar(baz(quux))) OR ip2 < foo(bar(baz(quux)))然后这个值进行比较将最终计算多次。

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

谢谢

sql database postgresql postgresql-10
2个回答
2
投票

您可以使用横向连接:

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);

1
投票

你考虑过使用CTE吗?

例如,假设我们有下表

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)
);

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

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.