以下查询在Postgres 9.4.5中不起作用。
SELECT * FROM (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M, METRICATTRIBUTES AS A
WHERE M.NAME=A.NAME AND A.ISSTRING='FALSE'
) AS S1
WHERE CAST(S1.V AS NUMERIC)<0
我收到如下错误:
invalid input syntax for type numeric: "astringvalue"
请继续阅读,看看为什么我的查询过于复杂。
METRICS是一个度量,值对的表。值存储为字符串,VALUE字段的某些值实际上是字符串。 METRICATTRIBUTES表标识可能具有字符串值的度量标准名称。我从METRICS表的分析中填充了METRICATTRIBUTES表。
要检查,我跑了......
SELECT * FROM (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M, METRICATTRIBUTES AS A
WHERE M.NAME=A.NAME AND A.ISSTRING='FALSE'
) AS S1
WHERE S1.V LIKE 'a%'
这不会返回任何值(就像我期望的那样)。错误似乎在执行计划中。这看起来像这样(对不起,我不得不胖手指)
1 -> HAS JOIN
2 HASH COND: ((M.NAME::TEXT=(A.NAME)::TEXT))
3 SEQ SCAN ON METRICS M
4 FILTER: ((VALUE)::NUMERIC<0::NUMERIC)
5 -> HASH
6 -> Seq Scan on METRICATTRIBUTES A
7 Filter: (NOT ISSTRING)
我不是这方面的专家(只有1周的Postgres经验)但看起来Postgres在应用连接条件(第2行)之前尝试应用强制转换(第4行)。通过这样做,它将尝试将强制转换应用于无效的字符串值,这正是我想要避免的!
使用显式连接写这个没有任何区别。将它作为单个选择语句编写是我的第一次尝试,从不期待这种类型的问题。这也行不通。
有什么想法吗?
答案 0 :(得分:0)
正如您从计划中看到的那样,表格METRICS
正在全面扫描(Seq Scan
)并根据您的条件进行过滤:CAST(S1.V AS NUMERIC)<0
- 加入并不限制范围。
显然,您有一些行,其中包含METRICS.VALUE
中的非数字数据。
检查表格中是否有这样的行:
SELECT * FROM METRICS
WHERE NOT VALUE ~ '^([0-9].,e)*$'
请注意,很难用正则表达式捕获所有可能的组合,因此请查看以下相关问题:isnumeric() with PostgreSQL
列的名称VALUE
不合适,因为这个词is a reserved one。
编辑:如果您完全确定,那么连接的表格会生成所需的VALUE
- s,而不是使用CTEs,它们在PostgreSQL中具有优化围栏功能:
WITH S1 AS (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M
JOIN METRICATTRIBUTES AS A USING (NAME)
WHERE A.ISSTRING='FALSE'
)
SELECT *
FROM S1
WHERE CAST(S1.V AS NUMERIC)<0;