SQL vs NoSQL in 8 Examples. Practical guide to compare basic... | by Soner Yıldırım | Towards Data Science

Relational databases store data in tabular form with labelled rows and columns. Although relational databases usually provide a decent solution for storing data, speed and scalability might be an issue in some cases.
SQL (Structured Query Language) is used by most relational database managements systems to manage databases that store data in tabular form. NoSQL refers to non-SQL or non-relational database design. It still provides an organized way of storing data but not in tabular form.
Put aside the concern for speed and scalability, both SQL and NoSQL databases provide versatile and efficient ways to query data. It is a must for a database because the accessibility is of crucial importance as well.
In this article, we will cover 8 examples that demonstrate how to query a SQL and NoSQL database. The examples will cover how to:
Select data based on condition
Insert new items
Update existing items
Apply aggregation functions
I will complete the same tasks in both databases so that we can see the differences and similarities.
I will be using MySQL for SQL and MongoDB for NoSQL. Before starting with the examples, let’s briefly explain how data is stored in SQL and NoSQL.
SQL stores data in tabular form with labelled rows and columns. The common structures adapted by NoSQL databases to store data are key-value pairs, wide column, graph, or document. MongoDB stores data as documents. A document in MongoDB consists of field-value pairs. Documents are organized in a structure called “collection”. As an analogy, we can think of documents as rows in a table and collections as tables.
I have created a simple table in MySQL and collection in MongoDB with same data that contains features of some cars and their prices.
Here is a document that identifies one item in the car collection:
{ "_id" : ObjectId("600c626932e0e6419cee81a7"), "year" : "2017", "make" : "hyundai", "color" : "white", "km" : 22000, "price" : 32000}
In SQL, a data point (one car in our case) is identified by a row.
+------+---------+-------+-------+-------+| year | make    | color | km    | price |+------+---------+-------+-------+-------+| 2017 | hyundai | white | 22000 | 32000 |+------+---------+-------+-------+-------+
Find the cars made by Ford.
NoSQL (MongoDB):
We pass the condition to the find function. The “db” refers to the current database and “car” is the collection we are querying.
> db.car.find( {make: "ford"} ).limit(1).pretty(){ "_id" : ObjectId("600c63cf32e0e6419cee81ab"), "year" : "2017", "make" : "ford", "color" : "black", "km" : 34000, "price" : 28000}
There are more than one car made by Ford but I use the limit function to display only one.
The pretty function makes the output more readable and appealing. Here is how it looks without the pretty function.
> db.car.find( {make: "ford"} ).limit(1){ "_id" : ObjectId("600c63cf32e0e6419cee81ab"), "year" : "2017", "make" : "ford", "color" : "black", "km" : 34000, "price" : 28000 }
SQL (MySQL):
We select all columns (*) and specify the condition in the where clause.
mysql> select * from car    -> where make = "ford"    -> limit 1;+------+------+-------+-------+-------+| year | make | color | km    | price |+------+------+-------+-------+-------+| 2017 | ford | black | 34000 | 28000 |+------+------+-------+-------+-------+
Find the cars made by Ford in 2019.
NoSQL (MongoDB):
We can pass multiple conditions separated by comma to indicate the “and” logic on the conditions.
> db.car.find( {make: "ford", year: "2019"} ).pretty(){ "_id" : ObjectId("600c63cf32e0e6419cee81af"), "year" : "2019", "make" : "ford", "color" : "white", "km" : 8000, "price" : 42000}
SQL (MySQL):
It is similar to the previous example. We can combine multiple conditions in the where clause using the and operator.
mysql> select * from car    -> where make = "ford" and year = "2019";+------+------+-------+------+-------+| year | make | color | km   | price |+------+------+-------+------+-------+| 2019 | ford | white | 8000 | 42000 |+------+------+-------+------+-------+
Find the cars made by Ford or Hyundai in year 2017.
NoSQL (MongoDB):
We first combine the condition on the brand with the “or” logic and then combine with year using the “and” logic. The “$in” operator can be used for the “or” logic.
> db.car.find( {make: {$in: ["ford","hyundai"] } , year: "2017"} ).pretty(){ "_id" : ObjectId("600c626932e0e6419cee81a7"), "year" : "2017", "make" : "hyundai", "color" : "white", "km" : 22000, "price" : 32000}{ "_id" : ObjectId("600c63cf32e0e6419cee81ab"), "year" : "2017", "make" : "ford", "color" : "black", "km" : 34000, "price" : 28000}
SQL (MySQL):
The where clause accepts the “in” operator so we can specify the conditions similar to NoSQL.
mysql> select * from car    -> where make in ("ford","hyundai") and year = "2017";+------+---------+-------+-------+-------+| year | make    | color | km    | price |+------+---------+-------+-------+-------+| 2017 | hyundai | white | 22000 | 32000 || 2017 | ford    | black | 34000 | 28000 |+------+---------+-------+-------+-------+
Insert a new item.
NoSQL (MongoDB):
The “insertOne” function is used to insert a single document to a collection. We need to write the field-value pairs of the new document.
> db.car.insertOne(... {year: "2017", make: "bmw", color: "silver", ...  km: 28000, price: 39000}... ){ "acknowledged" : true, "insertedId" : ObjectId("600c6bc79445b834692e3b91")}
SQL (MySQL):
The “insert into” function is used to add a new row into a table. Unlike NoSQL, we do not need to write the column names. However, the order of values must match the order of columns in the table.
mysql> insert into car values     -> ("2017", "bmw", "silver", 28000, 39000);Query OK, 1 row affected (0.03 sec)
Update the brand “bmw” as “BMW”.
NoSQL (MongoDB):
The update function is used. We first pass the condition that indicates the documents to be updated and then pass the updated values along with the set keyword.
> db.car.update(... { make: "bmw" },... { $set: { make: "BMW" }},... { multi: true }... )WriteResult({ "nMatched" : 5, "nUpserted" : 0, "nModified" : 5 })
We need to use the multi parameter to update all the documents that meet the given condition. Otherwise, only one document gets updated.
SQL (MySQL):
We use the update statement as below:
mysql> update car    -> set make = "BMW"    -> where make = "bmw";Query OK, 5 rows affected (0.05 sec)Rows matched: 5  Changed: 5  Warnings: 0
Both SQL and NoSQL are highly versatile in terms of data aggregation while querying a database. For instance, we can easily calculate the average price for each brand.
NoSQL (MongoDB):
We use the aggregate function.
> db.car.aggregate([... { $group: { _id: "$make", avg_price: { $avg: "$price" }}}... ]){ "_id" : "hyundai", "avg_price" : 36333.333333333336 }{ "_id" : "BMW", "avg_price" : 47400 }{ "_id" : "ford", "avg_price" : 35333.333333333336 }
We first group the documents based on brands by selecting “$make” as id. The next part specifies both the aggregation function which is “$avg” in our case and the field to be aggregated.
If you are familiar with Pandas, the syntax is quite similar to the groupby function.
SQL (MySQL):
The group by clause is used to group the rows based on categories in the given column. The aggregate function is applied when selecting the column.
mysql> select make, avg(price)    -> from car    -> group by make;+---------+------------+| make    | avg(price) |+---------+------------+| BMW     | 47400.0000 || ford    | 35333.3333 || hyundai | 36333.3333 |+---------+------------+
We can implement conditions in the aggregate function. For each brand, let’s calculate the average price of cars made in 2019.
NoSQL (MongoDB):
We just need to add the match keyword to specify the condition.
> db.car.aggregate([... { $match: { year: "2019" }},... { $group: { _id: "$make", avg_price: { $avg: "$price" }}}... ]){ "_id" : "BMW", "avg_price" : 53000 }{ "_id" : "ford", "avg_price" : 42000 }{ "_id" : "hyundai", "avg_price" : 41000 }
SQL (MySQL):
We use both where and group by clauses as below:
mysql> select make, avg(price)    -> from car    -> where year = "2019"    -> group by make;+---------+------------+| make    | avg(price) |+---------+------------+| BMW     | 53000.0000 || ford    | 42000.0000 || hyundai | 41000.0000 |+---------+------------+
We have covered 8 examples that demonstrate basic operations to deal with SQL and NoSQL databases.
Both of them provide many more functions and methods to create more advanced queries. As a result, they can also be used as data analysis and manipulation tools.
Thank you for reading. Please let me know if you have any feedback.