# Cypher 查询语言和 SQL 的对比 Cypher 就像 SQL 是一种声明性的文本查询语言,但用于图Graph。它由子句、关键字和表达式(如谓词和函数)组成,其中许多是熟悉的(如`WHERE`、`ORDER BY`、`SKIP LIMIT`、`AND`、`p.unitPrice > 10`)。与 SQL 不同,Cypher 是关于表达图模式的。我们添加了一个特殊子句`MATCH`来**匹配**您数据中的这些模式。这些图是您通常在白板上绘制的图,只是使用**ASCII 艺术符号**转换为文本。 关系数据库将数据存储在具有固定结构(架构)的表中,每列都有一个名称、类型、长度、约束等。表之间的引用通过将一个表的主键作为另一个表中的列作为外键重复来表示。对于多对多引用,需要连接表(或链接表)作为连接表之间的人工构造。 一个良好归一化的关系模型可以直接转换为等效的图模型。图模型主要是由用例驱动的,因此之后会有优化和模型演化的机会。 一个好的、规范化的实体关系图通常已经代表了一个不错的图模型。因此,如果您仍有可用的数据库的原始 ER 图,请尝试将其用作指南。 以NorthWind数据集为例,如果您必须在 SQL 中表达类别、地区或组织层次结构,那么您通常通过从子项到父项的外键使用自联接对其进行建模。添加数据没有问题,单级查询也是如此(获取此父级的所有子级)。一旦您进入多级查询,联接的数量就会激增,尤其是在您的级别深度不固定的情况下。 以产品类别为例,我们必须预先决定要查询的类别级别。我们将在这里只处理三个潜在级别(这意味着 ProductCategory 表的 1+2+3 = 6 个自连接)。 ```sql SELECT p.ProductName FROM Product AS p JOIN ProductCategory pc ON (p.CategoryID = pc.CategoryID AND pc.CategoryName = "Dairy Products") JOIN ProductCategory pc1 ON (p.CategoryID = pc1.CategoryID JOIN ProductCategory pc2 ON (pc2.ParentID = pc2.CategoryID AND pc2.CategoryName = "Dairy Products") JOIN ProductCategory pc3 ON (p.CategoryID = pc3.CategoryID JOIN ProductCategory pc4 ON (pc3.ParentID = pc4.CategoryID) JOIN ProductCategory pc5 ON (pc4.ParentID = pc5.CategoryID AND pc5.CategoryName = "Dairy Products") ; ``` Cypher 能够通过适当的关系表达任何深度的层次结构。可变级别由可变长度路径表示,`*`在关系类型和可选限制 ( `min..max`)后面用星号表示。 ```cypher MATCH (p:Product)-[:CATEGORY]->(l:ProductCategory)-[:PARENT*0..]-(:ProductCategory {name:"Dairy Products"}) RETURN p.name ``` Cypher 的内容远不止这一小节中显示的内容。希望与 SQL 的比较有助于您理解这些概念。如果您对这些可能性感兴趣并想尝试了解更多信息,只需在您的机器上[安装 Neo4j](https://neo4j.com/download)并使用指向我们不同 Cypher 学习资源的链接。 问题: 我们想看看谁买了*巧克力*。把这四个表连起来,不确定的时候参考模型(ER图)。 ```sql SELECT DISTINCT c.CompanyName FROM customers AS c JOIN orders AS o ON (c.CustomerID = o.CustomerID) JOIN order_details AS od ON (o.OrderID = od.OrderID) JOIN products AS p ON (od.ProductID = p.ProductID) WHERE p.ProductName = 'Chocolade'; ``` 请问在Neo4j中如何查询? ## 答案 ```cypher MATCH (p:Product {productName:"Chocolade"})<-[:PRODUCT]-(:Order)<-[:PURCHASED]-(c:Customer) RETURN distinct c.companyName; ``` ## 选项 ### A ```cypher MATCH (p:Product {productName:"Chocolade"})<-[:PRODUCT]-(:Order)<-[:PURCHASED]-(c:Customer) RETURN distinct c.companyName; ``` ### B ```cypher MATCH (p:Product.productName:"Chocolade")<-[:PRODUCT]-(:Order)<-[:PURCHASED]-(c:Customer) RETURN distinct c.companyName; ``` ### C ```cypher MATCH (p:Product{"Chocolade"})<-[:PRODUCT]-(:Order)<-[:PURCHASED]-(c:Customer) RETURN distinct c.companyName; ```