Sql POSTGRES-计算(子)表达式错误为NULL
我在Postgres表中有传感器数据Sql POSTGRES-计算(子)表达式错误为NULL,sql,postgresql,rdbms,Sql,Postgresql,Rdbms,我在Postgres表中有传感器数据测量值,其中列有id,时间戳,s0,s1,s2 此外,在(id,timestamp)列上还有一个索引。我希望允许动态数学表达式(在下面的示例中:sin(s3)*0.1000/s5)用于计算派生值 SELECT timestamp, trunc((sin(s3) * 0.1000/s5)::numeric, 3) AS "calculated" FROM measurements WHERE id = 42 ORDER BY timestamp DESC
测量值
,其中列有id
,时间戳
,s0
,s1
,s2
此外,在(id,timestamp)
列上还有一个索引。我希望允许动态数学表达式(在下面的示例中:sin(s3)*0.1000/s5
)用于计算派生值
SELECT
timestamp,
trunc((sin(s3) * 0.1000/s5)::numeric, 3) AS "calculated"
FROM measurements
WHERE id = 42
ORDER BY timestamp DESC
LIMIT 10000;
显然,这很容易出现“零除”错误,这将导致查询失败。是否有方法捕获此错误并返回可能发生错误的计算值,例如NULL
灵感来自
postgres
函数eval_numeric(sensors int[],formula text)
,该函数解析公式并在异常时返回NULL
。上面SQL语句的第三行现在读取
trunc(eval_numeric(ARRAY[s3,s5],'sin(var1)*0.1/var2'), 3) AS "calculated"
这提供了所需的行为,但是EXPLAIN ANALYZE
报告的执行时间增加了20倍(~20ms->~400ms)。还有其他想法吗
更新
要计算的动态表达式来自web应用程序用户。因此,上面的公式只是一个示例(可能需要检查平方根的负参数)。我宁愿有一个通用的错误检查的可能性,也不愿意在数学表达式中有逻辑。这对最终用户来说会更容易,我可以验证允许的数学,例如使用数学解析器,从而防止SQL注入。您能将表达式更改为此吗
SELECT timestamp,
trunc((sin(s3) * 0.1000/nullif(s5, 0))::numeric, 3) AS "calculated",
FROM measurements
WHERE id = 42
ORDER BY timestamp DESC
LIMIT 10000;
这是完成您想做的事情的最简单方法。您还可以使用
大小写表达式:
SELECT
timestamp,
CASE WHEN s5 != 0
THEN trunc((sin(s3) * 0.1000/s5)::numeric, 3)
ELSE NULL AS "calculated",
FROM measurements
WHERE id = 42
ORDER BY timestamp DESC
LIMIT 10000;
这样做的潜在好处是,您可以使用任何您想要的内容替换该值,包括NULL
另一种选择是,如果您不关心会触发被零除的行,只需将检查s5
添加到WHERE
子句中,并在除法发生之前过滤掉这些行。感谢您这么快的回答。这似乎是可行的,而且速度很快。我宁愿数学表达式中没有逻辑。关于这一点,我将更新我的问题。但也许这是另一个问题。我接受你的回答。