比较 Cypher 与 SQL

尽管 Cypher® 与 SQL 之间存在显著差异,但仍然可以比较这两种语言并使用 Cypher 编写等效的 SQL 语句。此处使用 Northwind 数据集 以更好地说明比较。

有关图数据库和关系型数据库之间异同的更深入解释,请参阅 从关系型数据库过渡到图数据库

索引

索引在 SQL 和 Cypher 中均可用。它们使搜索特定的节点标签和属性组合更加高效。

Cypher 中的索引 仅用于查找查询的起点;所有后续模式匹配均通过图结构完成。Cypher 支持 范围、文本、点、查找、全文和向量索引。

在 Northwind 数据集中,在 `productName` 和 `unitPrice` 上添加索引可以更快地搜索产品及其价格。

SQL Cypher
CREATE INDEX Product_productName ON products (product_name);
CREATE INDEX Product_unitPrice ON products (unit_price);
CREATE INDEX Product_productName IF NOT EXISTS FOR (p:Product) ON p.productName;
CREATE INDEX Product_unitPrice IF NOT EXISTS FOR (p:Product) ON p.unitPrice;

查询示例

选择并返回记录

SQL Cypher

在 SQL 中,要选择并返回记录,请从 `products` 表中选择所有内容。

SELECT p.*
FROM products as p;

在 Cypher 中,您 `MATCH` 一个简单模式:所有带有 **标签** `:Product` 的节点,并 `RETURN` 它们。

MATCH (p:Product)
RETURN p;

字段访问、排序与分页

您可以过滤掉您感兴趣的属性,例如 `ProductName` 和 `UnitPrice`,而不是返回所有属性。

SQL Cypher

在 SQL 中,这是按价格排序并返回 10 个最昂贵项目的方式。

SELECT p.ProductName, p.UnitPrice
FROM products as p
ORDER BY p.UnitPrice DESC
LIMIT 10;

该语句在 Cypher 中类似,除了模式匹配部分。

MATCH (p:Product)
RETURN p.productName, p.unitPrice
ORDER BY p.unitPrice DESC
LIMIT 10;
结果
p.productName p.unitPrice

"Côte de Blaye"

263.5

"Thüringer Rostbratwurst"

123.79

"Mishi Kobe Niku"

97.0

"Sir Rodney’s Marmalade"

81.0

"Carnarvon Tigers"

62.5

"Raclette Courdavault"

55.0

"Manjimup Dried Apples"

53.0

"Tarte au sucre"

49.3

"Ipoh Coffee"

46.0

"Rössle Sauerkraut"

45.6

请记住,Neo4j 中的标签、关系类型和属性名称是**区分大小写**的。有关命名规则的更多详细信息,请参阅 Cypher 手册 → 命名规则和建议

按名称查找单个产品

有不同的方式来查询数据库并检索单个项目,例如,名为 `Chocolade` 的产品。您可以通过相等性过滤来完成此操作。

SQL Cypher

在 SQL 中,您可以使用 `WHERE` 子句过滤数据。

SELECT p.ProductName, p.UnitPrice
FROM products AS p
WHERE p.ProductName = 'Chocolade';

在 Cypher 中,`WHERE` 子句属于 `MATCH` 语句。

MATCH (p:Product)
WHERE p.productName = 'Chocolade'
RETURN p.productName, p.unitPrice;

一个更短的选择是使用标签 `productName` 在 `MATCH` 语句中指定产品。

MATCH (p:Product {productName:'Chocolade'})
RETURN p.productName, p.unitPrice;
结果
p.productName p.unitPrice

"Chocolade"

12.75

筛选产品

按列表/范围筛选

SQL Cypher

在 SQL 中,您可以使用运算符 `IN`。

SELECT p.ProductName, p.UnitPrice
FROM products as p
WHERE p.ProductName IN ('Chocolade','Chai');

Cypher 具有完整的集合支持,包括 `IN` 和其他集合函数、谓词和转换。

MATCH (p:Product)
WHERE p.productName IN ['Chocolade','Chai']
RETURN p.productName, p.unitPrice;
结果
p.productName p.unitPrice

"Chocolade"

12.75

"Chai"

18.0

按多个数值和文本谓词筛选

SQL Cypher

此查询检索名称以“C”开头且价格大于 100 的产品。

SELECT p.ProductName, p.UnitPrice
FROM products AS p
WHERE p.ProductName LIKE 'C%' AND p.UnitPrice > 100;

在 Cypher 中,`LIKE` 运算符被 `STARTS WITH`、`CONTAINS` 和 `ENDS WITH` 运算符取代。

MATCH (p:Product)
WHERE p.productName STARTS WITH 'C' AND p.unitPrice > 100
RETURN p.productName, p.unitPrice;

您还可以使用正则表达式获取所有名称以“C”开头的产品及其价格。

MATCH (p:Product)
WHERE p.productName =~ '^C.*'
RETURN p.productName, p.unitPrice
结果
p.productName p.unitPrice

"Côte de Blaye"

263.5

将产品与客户连接

SQL Cypher

在 SQL 中,如果您想查看谁购买了 `Chocolade`,可以将四个表连接在一起。

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';

在 Cypher 中,无需 `JOIN` 表。您可以改为将连接表示为图模式。

MATCH (p:Product {productName:'Chocolade'})<-[:ORDERS]-(:Order)<-[:PURCHASED]-(c:Customer)
RETURN DISTINCT c.companyName;
结果
c.companyName

"Victuailles en stock"

"Ernst Handel"

"Antonio Moreno Taquería"

"Furia Bacalhau e Frutos do Mar"

"Around the Horn"

"Queen Cozinha"

每个产品的总花费

通过汇总产品价格和订购数量,可以为客户提供每个产品的聚合视图。您可以在 SQL 和 Cypher 中使用 `sum`、`count`、`avg` 和 `max` 等聚合函数。

SQL Cypher

如果您想查看一家公司(例如 Drachenblut Delikatessen)为每种产品总共支付了**多少**,包括他们没有产品订单的情况,您必须使用 `OUTER JOINS` 以确保即使其他表中没有匹配的行也能返回结果。

SELECT p.Product_Name, sum(od.Unit_Price * od.Quantity) AS TotalPrice
FROM customers AS c
LEFT OUTER JOIN orders AS o ON (c.Customer_ID = o.Customer_ID)
LEFT OUTER JOIN order_details AS od ON (o.Order_ID = od.Order_ID)
LEFT OUTER JOIN products AS p ON (od.Product_ID = p.Product_ID)
WHERE c.Company_Name = 'Drachenblut Delikatessen'
GROUP BY p.Product_Name;

在 Cypher 中,您需要将 `ORDERS` 关系的 `unitPrice` 属性转换为整数,以便计算订购数量和花费金额。

MATCH (p:Product)<-[o:ORDERS]-(order:Order)
SET o.unitPrice = toInteger(o.unitPrice)
RETURN o

然后您 `MATCH` 要从中收集信息的公司,并使用 `OPTIONAL MATCH` 查找其购买和获得的产品,然后 `RETURN` 总和。

MATCH (c:Customer {companyName:'Drachenblut Delikatessen'})
OPTIONAL MATCH (c)-[:PURCHASED]->(:Order)-[o:ORDERS]->(p:Product)
RETURN p.productName, toInteger(sum(o.unitPrice * o.quantity)) AS totalPrice
结果
p.productName totalPrice

"Gumbär Gummibärchen"

372

"Perth Pasties"

640

"Konbu"

114

"Jack’s New England Clam Chowder"

81

"Queso Cabrales"

420

"Raclette Courdavault"

1650

"Lakkalikööri"

168

"Rhönbräu Klosterbier"

72

"Gorgonzola Telino"

200

供应的产品数量

上一个示例提到了聚合,并使用 `SUM` 函数来计算公司在购买特定产品时花费了多少。您还可以使用 Cypher 中的 `COUNT` 函数来计算供应商提供了多少产品,例如。

SQL Cypher

在 SQL 中,聚合是显式的,因此您必须在 `GROUP BY` 子句中再次提供所有分组键。

SELECT s.CompanyName AS Supplier, COUNT(p.ProductID) AS NumberOfProducts
FROM Suppliers s
JOIN Products p ON s.SupplierID = p.SupplierID
GROUP BY s.CompanyName
ORDER BY NumberOfProducts DESC
LIMIT 5;

在 Cypher 中,聚合的分组是隐式的。一旦您使用第一个聚合函数,所有非聚合列将自动成为分组键。

MATCH (s:Supplier)<-[:SUPPLIED_BY]-(p:Product)
RETURN s.companyName AS Supplier, COUNT(p) AS NumberOfProducts
ORDER BY NumberOfProducts DESC
LIMIT 5

还提供了其他聚合函数,如 `collect`、`percentileCont`、`stdDev`。

结果
供应商 产品数量

"Pavlova"

5

"Plutzer Lebensmittelgroßmärkte AG"

5

"Specialty Biscuits"

4

"New Orleans Cajun Delights"

4

"Grandma Kelly’s Homestead"

3

供应产品列表

在 Cypher 中,您可以使用 `COLLECT` 函数收集所有连接到其他节点的节点,但 SQL 没有直接等效的函数。

SQL Cypher

在 SQL 中,如果您想列出供应商提供的产品,可以使用 `STRING_AGG`。

SELECT s.CompanyName AS Supplier, STRING_AGG(p.ProductName, ', ' ORDER BY p.ProductName) AS ProductsSupplied
FROM Suppliers s
JOIN Products p ON s.SupplierID = p.SupplierID
GROUP BY s.CompanyName
ORDER BY s.CompanyName
LIMIT 5;

在 Cypher 中,您可以像 SQL 中一样返回结构,或者使用 `collect()` 聚合函数,该函数将值聚合到集合(列表、数组)中。这样,每个父级只返回一行,其中包含子值的内联集合。

MATCH (s:Supplier)-[:SUPPLIES]->(p:Product)
RETURN s.companyName AS Supplier, COLLECT(p.productName) AS ProductsSupplied
ORDER BY Supplier
LIMIT 5

这也适用于嵌套值。

结果
供应商 供应产品

"Aux joyeux ecclésiastiques"

["Côte de Blaye", "Chartreuse verte"]

"Bigfoot Breweries"

["Sasquatch Ale", "Laughing Lumberjack Lager", "Steeleye Stout"]

"Cooperativa de Quesos 'Las Cabras'"

["Queso Manchego La Pastora", "Queso Cabrales"]

"Escargots Nouveaux"

["Escargots de Bourgogne"]

"Exotic Liquids"

["Aniseed Syrup", "Chang", "Chai"]

© . All rights reserved.