2014-04-22 77 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);

改善查詢,我們可以對時間戳即值屬性的索引的性能。