2016-08-31 17 views
1

SQLでは、whereはオプションです(存在しない)。これは、他のSELECTの結果がゼロの場合にのみ行を選択できるようにします。例えばNeo4j Cypher MATCH(存在しない場合)

SELECT 
    c.CustomerKey 
FROM 
    Customer c, Sales s1, Date d 
WHERE 
    s1.CustomerKey = c.CustomerKey AND 
    s1.OrderDateKey = d.DateKey AND 
    s1.ShipDate > s1.DueDate AND 
    NOT EXISTS (SELECT * 
       FROM Sales s2 
       WHERE s2.OrderDateKey = s1.OrderDateKey AND 
         s2.CustomerKey <> s1.CustomerKey) 
GROUP BY 
    c.CustomerKey 

私は、次の操作を実行しようとしましたが、クエリはので、私は、私はそれを間違った方法をやっていると仮定決して終わりません。私は何が欠けていますか?

MATCH (d1:Date)<-[:ORDERDATE]-(s1:Sales)-[:CUSTOMER]->(c1:Customer) 
WHERE s1.ShipDate > s1.DueDate 
WITH d1,s1,c1 
MATCH (s2:Sales)-[:CUSTOMER]->(c2:Customer) 
WHERE NOT(s2.OrderDateKey=s1.OrderDateKey AND c2.CustomerKey<>c1.CustomerKey) 
RETURN c2.CustomerKey 
+0

CustomerKeyは顧客を一意に識別しますか? – InverseFalcon

答えて

2

以下のクエリは、必要な操作を行う必要があります。

まず、以下のクエリでOPTIONAL MATCHはすぐに(代わりにそれらのすべてをスキャンする)希望Salesのノードを見つけることができるように、あなたは:Sales(OrderDateKey)にインデックスを作成する必要があります。

CREATE INDEX ON :Sales(OrderDateKey); 

OPTIONAL MATCH句がに失敗した場合一致するものを見つけると、バインドされていない識別子をNULLに設定します。次のクエリは、その事実を利用しています:我々はまだやるべき時

MATCH (:Date)<-[:ORDERDATE]-(s1:Sales)-[:CUSTOMER]->(c1:Customer) 
WHERE s1.ShipDate > s1.DueDate 
WITH s1.OrderDateKey AS odk, c1.CustomerKey AS customerKey 
OPTIONAL MATCH (s2:Sales)-[:CUSTOMER]->(c2:Customer) 
WHERE s2.OrderDateKey=odk AND c2.CustomerKey<>customerKey 
WITH customerKey 
WHERE c2 IS NULL 
RETURN DISTINCT customerKey; 
+0

CustomerKeyが顧客を一意に識別する場合(質問者は明確にする必要があります)、CustomerKeyをまったく使用する必要はありません。単に 'c1'を渡し、' WHERE'に 'AND c1 <> c2'を使用するだけです。句。 – InverseFalcon

+0

もしそれができたとしても、それはおそらくクエリを高速化しません。 – cybersam

+0

おそらくそうではありません。可能であればプロパティー値を超えるノードを使用する方が好きです(パフォーマンスの影響はありません)。特にSQLからCypherに変換する場合は特にそうです。 SQLはすべて結合と外部キーについてですが、Cypherではリレーションシップとパターンマッチングを使用する必要があります。私は、Cypherのベストプラクティスをより奨励するために、これらのキーの使用方法から離れることをお勧めします。 – InverseFalcon

1

サイファーにSQLを変換するのトリッキーな部分が把握されて参加し、述語鍵に基づいて、対我々はの用法にそれらの操作を変換する必要があるときノードと関係。

てみましょう最初のSQLは、私が言うことができるように最善のように、何を意味するのか翻訳:

我々は 販売の出荷日が期日を過ぎている顧客と注文日、セールをマッチさせたいです異なる顧客の注文日が同じのセールスはまだありません。

Sales.OrderDateKeyはDate.DateKeyの主キーの外部キーで、Sales.CustomerKeyはCustomer.CustomerKeyの主キーの外部キーです。

上記の仮定が真であれば、これらのキーを使用する必要はありません。SQLは外部キーと主キーを使用して結合するため、Neo4jはノード間の関係を代わりに使用するため、返された値を除いて実際にこれらのフィールドをこのクエリ内のものに使用します。

MATCH (orderDate:Date)<-[:ORDERDATE]-(s1:Sales)-[:CUSTOMER]->(c1:Customer) 
WHERE s1.ShipDate > s1.DueDate 
WITH orderDate, c1 
// match to exclude is a sale with the same orderDate but different customer 
OPTIONAL MATCH (orderDate)<-[:ORDERDATE]-(:Sales)-[:CUSTOMER]->(c2:Customer) 
WHERE c1 <> c2 
WITH c1 
WHERE c2 IS NULL 
RETURN DISTINCT c1.customerKey;