我必须删除表中的行,这是基于与其中一列上的一个非常长的函数应用程序的多次比较。为了详细介绍,我正在从base64解码,做一个子串,转换为json
,取一个特定的字段,然后将其转换为inet
。
我正在使用那些ips与我的WHERE
子句中的其他ips / mask进行比较。
我遇到的问题是获得实际结果是一个相当长的字符串,如果我最终说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吗?
例如,假设我们有下表
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
部分使用预先精确的列。