2014-04-22 76 views
1

我试图在查询中使用UNION创建发票产品子图,然后只想将使用WITH的发票节点传递给子查询。它看起来像下面Neo4J Cypher - Union&With子句用法

MATCH (year:Year)-[]->(month:Month)-[]->(day:Day)-[]->(inv:Invoice)-[]->(prd:Product) 
WHERE year.value='2014' and day.value IN ['27','28','29','30','31'] and month.value='January' 
RETURN (inv:Invoice)-[:PRODUCT]->(prd:Product) 
UNION 
MATCH (year:Year)-[]->(month:Month)-[]->(day:Day)-[]->(inv:Invoice)-[]->(prd:Product) 
WHERE year.value='2014' and day.value IN ['01','02','03','04'] and month.value='February' 
WITH inv 
MATCH (inv)-[p:PROCESSED_AT]-(time:Time) WHERE p.time > 700 and p.time < 900 
RETURN inv.invid 

但我收到此错误 - UNION中的所有子查询必须具有相同的列名称。任何输入在哪里我会错在这里?

回答

1

我认为这个错误很明显,你的UNION的2个部分没有返回相同数量的列来创建一个联合。如果我理解正确,您正试图获取具有无效时间戳的特定产品的所有发票。我不认为如果是这种情况,你将需要一个联盟,而你可能需要一个WITH子句。

不管怎么说,修复可能要只是2份UNION的匹配如下

MATCH (year:Year)-[]->(month:Month)-[]->(day:Day)-[]->(inv:Invoice)-[]->(prd:Product) 
WHERE year.value='2014' and day.value IN ['27','28','29','30','31'] and month.value='January' 
MATCH (inv:Invoice)-[:PRODUCT]->(prd:Product) 
RETURN inv, prd 
UNION 
MATCH (year:Year)-[]->(month:Month)-[]->(day:Day)-[]->(inv:Invoice)-[]->(prd:Product) 
WHERE year.value='2014' and day.value IN ['01','02','03','04'] and month.value='February' 
WITH inv 
MATCH (prd:Product)<-[:PRODUCT]-(inv)-[p:PROCESSED_AT]-(time:Time) WHERE p.time > 700 and p.time < 900 
RETURN inv, prd 

上面的查询。

编辑

我想你已经得到了UNIONRETURNWITH有点过了,说实话我不知道我们如何使用UNION加入2分的结果,然后使用WITH缝合它到另一个查询。不过,我认为你可以用一个简单的重新排列加入类似下面

MATCH (year:Year)-[]->(month:Month)-[]->(day:Day)-[]->(inv:Invoice)-[]->(prd:Product) 
WHERE year.value='2014' and ((day.value IN ['27','28','29','30','31'] and month.value='January') or (day.value IN ['01','02','03','04'] and month.value='February')) 
WITH inv 
MATCH (inv)-[p:PROCESSED_AT]-(time:Time) WHERE p.time > 700 and p.time < 900 
RETURN inv.invid 
+0

也许还需要用'AS columnName'替换RETURN中的列 –

+0

我试过上面的查询,但它没有工作,它仍然给出相同的错误... – deepesh

+0

@DeepeshKuruppath:我编辑的查询,你可以试试看,如果它的工作 – Kiran

0

你可以通过用逗号分隔的多个短语来匹配前提是它们构成了一个连通图解决这个非常的问题,这将简化您的问题。

MATCH (year:Year)-[]->(month:Month)-[]->(day:Day)-[]->(inv:Invoice)-[]->(prd:Product) 
WHERE year.value='2014' and day.value IN ['01','02','03','04'] and month.value='February' 
WITH inv 
MATCH (prd:Product)<-[:PRODUCT]-(inv)-[p:PROCESSED_AT]-(time:Time) WHERE p.time > 700 and p.time < 900 
RETURN inv, prd 

可以成为:

MATCH (year:Year)-[]->(month:Month)-[]->(day:Day)-[]->(inv:Invoice)-[]->(prd:Product), 
(prd:Product)<-[:PRODUCT]-(inv)-[p:PROCESSED_AT]-(time:Time) 
WHERE p.time > 700 and p.time < 900 
RETURN inv, prd 

,您可以查询上半年同样简化。

此外,使用联合时,返回的列名必须匹配每个返回子句。

+0

谢谢这很有帮助,我改变了我的设计,以避免这种联合使用情况。 – deepesh

+0

那么upvote答案:) –

+1

它说投票需要15名誉:( – deepesh

0

我最终通过改变总体设计来避免使用UNION,从而解决了这个问题。一种方法是将Timestamps定义为单个实体,而不是分别将它们存储为Year,Month和Date。

即添加时间节点如下图所示

//Add TimeStamp Nodes CREATE (datets1: DateTS {value:201401270730}) CREATE (datets2: DateTS {value:201401270800}) CREATE (datets3: DateTS {value:201401280745}) CREATE (datets4: DateTS {value:201402020815}) CREATE (datets5: DateTS {value:201402020830}) CREATE (datets6: DateTS {value:201402030702})

注 - 在我的情况,我不需要秒和毫秒,所以它只是具体到小时和分钟分辨率结束。

现在,我在图中这些节点的事件相关联,然后将查询变得非常简单,像 MATCH (inv)-[:DATETIME]->(dts) WHERE dts.value <=201401280900 and dts.value >= 201401280700 RETURN distinct(inv.invid);

改善查询,我们可以对时间戳即值属性的索引的性能。