Neo4j 将 ( / ) 除以零 ( 0 )
Neo4j Divide ( / ) by Zero ( 0 )
我在neo4j中查询
MATCH (n)-[t:x{x:"1a"}]->()
WHERE n.a > 1 OR n.b > 1 AND toFloat(n.a) / (n.a+n.b) * 100 < 90
RETURN DISTINCT n, toFloat(n.a) / (n.a + n.b) * 100
ORDER BY toFloat(n.a) / (n.a + n.b) * 100 DESC
LIMIT 10
但是我遇到了 / by zero
错误。
因为我声明 n.a 或 n.b 之一应该是 1,如果两者都为零,它应该跳过该行,我不应该得到这个错误。这看起来像是 Neo4j 中的逻辑问题。当我从 WHERE 子句中删除 AND toFloat(n.a)/(n.a+n.b)*100 < 90
时没有问题。但我希望结果只低于 90。我该如何克服这个问题?
n.a
或 n.b
都可以为负数吗?我能够通过以下方式重现此内容:
WITH -2 AS na, 2 AS nb
WHERE (na > 1 OR nb > 1) AND toFloat(na)/(na+nb)*100 < 90
RETURN na, nb
我得到:/ by zero
也许尝试将 WHERE
子句更改为:
WITH -2 AS na, 2 AS nb
WHERE (na + nb > 0) AND toFloat(na)/(na+nb)*100 < 90
RETURN na, nb
我得到:零行。
似乎第二个条件 toFloat(na) / (na + nb) * 100 < 90
在第一个条件之前进行了测试。看这个执行计划中的Filter(1)
运算符:
+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Operator | EstimatedRows | Rows | DbHits | Identifiers | Other |
+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Projection | 1 | 3 | 0 | anon[111], anon[138], n, toFloat(n.a)/(n.a + n.b)* 100 | anon[111]; anon[138] |
| Top | 1 | 3 | 0 | anon[111], anon[138] | { AUTOINT6}; |
| Distinct | 0 | 3 | 24 | anon[111], anon[138] | anon[111], anon[138] |
| Filter(0) | 0 | 3 | 6 | anon[29], n, t | t.x == { AUTOSTRING0} |
| Expand(All) | 1 | 3 | 6 | anon[29], n, t | ( n@7)-[t:x]->() |
| Filter(1) | 1 | 3 | 34 | n | (Ors(List(n@7.a > { AUTOINT1}, Multiply(Divide(ToFloatFunction( n@7.a),Add( n@7.a, n@7.b)),{ AUTOINT3}) < { AUTOINT4})) AND Ors(List( n@7.a > { AUTOINT1}, n.b > { AUTOINT2}))) |
| AllNodesScan | 4 | 4 | 5 | n | |
+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
您可以通过强制将过滤器分成两个子句来解决这个问题。
MATCH (n)-[t:x { x:"1a" }]->()
WHERE n.a > 1 OR n.b > 1
WITH n
WHERE toFloat(n.a) / (n.a + n.b) * 100 < 90
RETURN DISTINCT n, toFloat(n.a) / (n.a + n.b) * 100
ORDER BY toFloat(n.a) / (n.a + n.b) * 100 DESC
LIMIT 10
我发现这种行为令人惊讶,但当我想到它时,我认为执行引擎以这种方式重新排列过滤器并没有错。可能假设条件会在第一个声明的条件失败时提前放弃,但 Cypher 正是这样:声明性的。所以我们表达的是"what",而不是"how",在"what"方面,A and B
等价于B and A
。
这是查询和示例图,您可以检查它是否转换为您的实际数据:
http://console.neo4j.org/r/f6kxi5
我在neo4j中查询
MATCH (n)-[t:x{x:"1a"}]->()
WHERE n.a > 1 OR n.b > 1 AND toFloat(n.a) / (n.a+n.b) * 100 < 90
RETURN DISTINCT n, toFloat(n.a) / (n.a + n.b) * 100
ORDER BY toFloat(n.a) / (n.a + n.b) * 100 DESC
LIMIT 10
但是我遇到了 / by zero
错误。
因为我声明 n.a 或 n.b 之一应该是 1,如果两者都为零,它应该跳过该行,我不应该得到这个错误。这看起来像是 Neo4j 中的逻辑问题。当我从 WHERE 子句中删除 AND toFloat(n.a)/(n.a+n.b)*100 < 90
时没有问题。但我希望结果只低于 90。我该如何克服这个问题?
n.a
或 n.b
都可以为负数吗?我能够通过以下方式重现此内容:
WITH -2 AS na, 2 AS nb
WHERE (na > 1 OR nb > 1) AND toFloat(na)/(na+nb)*100 < 90
RETURN na, nb
我得到:/ by zero
也许尝试将 WHERE
子句更改为:
WITH -2 AS na, 2 AS nb
WHERE (na + nb > 0) AND toFloat(na)/(na+nb)*100 < 90
RETURN na, nb
我得到:零行。
似乎第二个条件 toFloat(na) / (na + nb) * 100 < 90
在第一个条件之前进行了测试。看这个执行计划中的Filter(1)
运算符:
+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Operator | EstimatedRows | Rows | DbHits | Identifiers | Other |
+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Projection | 1 | 3 | 0 | anon[111], anon[138], n, toFloat(n.a)/(n.a + n.b)* 100 | anon[111]; anon[138] |
| Top | 1 | 3 | 0 | anon[111], anon[138] | { AUTOINT6}; |
| Distinct | 0 | 3 | 24 | anon[111], anon[138] | anon[111], anon[138] |
| Filter(0) | 0 | 3 | 6 | anon[29], n, t | t.x == { AUTOSTRING0} |
| Expand(All) | 1 | 3 | 6 | anon[29], n, t | ( n@7)-[t:x]->() |
| Filter(1) | 1 | 3 | 34 | n | (Ors(List(n@7.a > { AUTOINT1}, Multiply(Divide(ToFloatFunction( n@7.a),Add( n@7.a, n@7.b)),{ AUTOINT3}) < { AUTOINT4})) AND Ors(List( n@7.a > { AUTOINT1}, n.b > { AUTOINT2}))) |
| AllNodesScan | 4 | 4 | 5 | n | |
+--------------+---------------+------+--------+--------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
您可以通过强制将过滤器分成两个子句来解决这个问题。
MATCH (n)-[t:x { x:"1a" }]->()
WHERE n.a > 1 OR n.b > 1
WITH n
WHERE toFloat(n.a) / (n.a + n.b) * 100 < 90
RETURN DISTINCT n, toFloat(n.a) / (n.a + n.b) * 100
ORDER BY toFloat(n.a) / (n.a + n.b) * 100 DESC
LIMIT 10
我发现这种行为令人惊讶,但当我想到它时,我认为执行引擎以这种方式重新排列过滤器并没有错。可能假设条件会在第一个声明的条件失败时提前放弃,但 Cypher 正是这样:声明性的。所以我们表达的是"what",而不是"how",在"what"方面,A and B
等价于B and A
。
这是查询和示例图,您可以检查它是否转换为您的实际数据:
http://console.neo4j.org/r/f6kxi5