Comparing Cypher with SQL
While there are key differences between Cypher® and SQL, it is still possible to compare both languages and write equivalent SQL statements using Cypher. The Northwind dataset is used here to better illustrate the comparison.
For a more in-depth explanation on the differences and similarities between graph and relational databases, see Transition from relational to graph database. |
Indexing
Indexes are available both in SQL and Cypher. They make searching for a specific node label and attribute combination more efficient.
Indexes in Cypher are only used for finding the starting points of a query; all subsequent pattern matching is done through the graph structure. Cypher supports range, text, point, lookup, full-text, and vector indexes.
In the Northwind dataset, adding indexes on productName
and unitPrice
makes searching for a product and its price quicker:
SQL | Cypher |
---|---|
|
|
Query examples
Select and return records
SQL | Cypher |
---|---|
To select and return records in SQL, select everything from the
|
In Cypher, you
|
Field access, ordering, and paging
Rather than returning all attributes, you can filter out the ones you are interested in — ProductName
and UnitPrice
, for example.
SQL | Cypher |
---|---|
In SQL, this is how you order items by price and return the 10 most expensive items:
|
The statement is similar in Cypher, except for the pattern matching part:
|
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 |
Remember that labels, relationship types, and property names are case sensitive in Neo4j. For more details on naming rules, see the Cypher Manual → Naming rules and recommendations. |
Find a single product by name
There are different ways to query the database and retrieve a single item, for example, a product named Chocolade
.
You can do that, for example, by filtering by equality:
SQL | Cypher |
---|---|
In SQL, you can filter data using the
|
In Cypher, the
A shorter option is to use the label
|
p.productName | p.unitPrice |
---|---|
"Chocolade" |
12.75 |
Filter products
Filter by list/range
SQL | Cypher |
---|---|
In SQL, you can use the operator
|
Cypher has full collection support, including
|
p.productName | p.unitPrice |
---|---|
"Chocolade" |
12.75 |
"Chai" |
18.0 |
Filter by multiple numeric and textual predicates
SQL | Cypher |
---|---|
This query retrieves products with a name starting with "C" and a price larger than 100:
|
In Cypher, the
You can also use a regular expression to get all products with name starting with "C" and their prices:
|
p.productName | p.unitPrice |
---|---|
"Côte de Blaye" |
263.5 |
Joining products with customers
SQL | Cypher |
---|---|
In SQL, if you want to see who bought
|
In Cypher, there is no need to
|
c.companyName |
---|
"Victuailles en stock" |
"Ernst Handel" |
"Antonio Moreno Taquería" |
"Furia Bacalhau e Frutos do Mar" |
"Around the Horn" |
"Queen Cozinha" |
Total spent in each product
By summing up product prices and ordered quantities, an aggregated view per product for the customer is provided.
You can use aggregation functions like sum
, count
, avg
, and max
in both SQL and Cypher.
SQL | Cypher |
---|---|
If you want to see what a company (e.g. Drachenblut Delikatessen) paid in total per product, including where they had no orders for products, you have to use
|
In Cypher, you need to turn the
Then you
|
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 |
Amount of products supplied
The previous example mentioned aggregation and used the SUM
function to find out how much a company has spent when purchasing specific products.
You can use the COUNT
function in Cypher to also count how many products are offered by a supplier, for example.
SQL | Cypher | ||
---|---|---|---|
In SQL, aggregation is explicit, so you have to provide all grouping keys again in the
|
In Cypher, grouping for aggregation is implicit. As soon as you use the first aggregation function, all non-aggregated columns automatically become grouping keys:
|
Supplier | NumberOfProducts |
---|---|
"Pavlova" |
5 |
"Plutzer Lebensmittelgroßmärkte AG" |
5 |
"Specialty Biscuits" |
4 |
"New Orleans Cajun Delights" |
4 |
"Grandma Kelly’s Homestead" |
3 |
List of products supplied
In Cypher you can use the COLLECT
function to gather all nodes connected to others, but SQL doesn’t have a direct equivalent to it.
SQL | Cypher | ||
---|---|---|---|
In SQL, if you want a lit of what products the suppliers offer, you use
|
In Cypher, you can either return the structure like in SQL or use the
|
Supplier | ProductsSupplied |
---|---|
"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"] |