Supermarket Data Analysis with SQL | by Soner Yıldırım | Towards Data Science

SQL is a programming language used to manage data in relational databases which store data in tabular form with labelled rows and columns. SQL is a fundamental tool to put in your skill set if you plan to work in the field of data science.
We can query a database to retrieve data without any modification or filtering. However, this is not a proactive or efficient way. We are most likely to apply some data manipulation or filtering on the raw data to make it more useful.
SQL is highly capable of doing data manipulation and filtering operations. The advantage of using SQL for such tasks is that we just need to retrieve the data we need instead of getting all at once. Furthermore, it allows for doing data analysis while retrieving the data.
In this article, we will be analyzing a supermarket sales dataset available on Kaggle. I have done some modifications on the dataset and simplified it by excluding some of the columns. I have created a table in a MySQL database with the modified version of the dataset.
The dataset contains the details of sales at different branches of a supermarket chain during a period of 3 months.
Note: I wrote another practical article on this dataset using Pandas, a highly popular data analysis and manipulation library for Python.
We may want to sort the product categories based on the total sales amounts.
mysql> select prod_line, sum(total)    -> from supermarket    -> group by prod_line    -> order by sum(total) desc;+----------------------+------------+| prod_line            | sum(total) |+----------------------+------------+| Food and beverages   |   56144.86 || Sports and travel    |   55122.88 || Electronic accessori |   54337.52 || Fashion accessories  |   54305.88 || Home and lifestyle   |   53861.87 || Health and beauty    |   49193.81 |+----------------------+------------+
We first select the columns and apply the aggregation. The next step is to group the aggregated column by the product categories. Finally, we sort the results in descending order based on the total sales amounts.
Customer type and gender columns can be used to get an overview about the customer portfolio. We can count the number of purchases that belong to each cross category.
mysql> select cust_type, gender, count(*)    -> from supermarket    -> group by cust_type, gender;+-----------+--------+----------+| cust_type | gender | count(*) |+-----------+--------+----------+| Member    | Female |      261 || Member    | Male   |      240 || Normal    | Female |      240 || Normal    | Male   |      259 |+-----------+--------+----------+
The distribution is quite balanced with regards to the customer type and gender columns.
The where clause can be implemented in a select statement to apply conditions on the selected rows. For instance, we can calculate the average quantities of purchases with a total amount higher than 500.
mysql> select avg(qty)    -> from supermarket    -> where total > 500;+----------+| avg(qty) |+----------+|   8.3744 |+----------+mysql> select avg(qty)    -> from supermarket;+----------+| avg(qty) |+----------+|   5.5100 |+----------+
The condition is applied in the first query above. The second query returns the average quantity for the entire table.
We can apply a condition based on dates. For instance, the following query returns all of the sales made between 2019–01–05 and 2019–01–07.
mysql> select *    -> from supermarket    -> where date between "2019-01-05" and "2019-01-07";
Consider we need to find the top 5 dates with the highest total sales amount. We first need to group the sales based on date because there are many purchases in each day. After that, the results are sorted in descending order based on total sales amount and the first 5 are selected.
mysql> select date, sum(total)    -> from supermarket    -> group by date    -> order by sum(total) desc    -> limit 5;+------------+------------+| date       | sum(total) |+------------+------------+| 2019-03-09 |    7474.04 || 2019-02-07 |    7228.22 || 2019-03-14 |    7214.62 || 2019-02-15 |    6830.78 || 2019-03-02 |    6560.30 |+------------+------------+
Let’s assume we need to find the date of the sales with the maximum total amount. There are multiple ways of doing this task. One is to use nested select statements as below:
mysql> select date     -> from supermarket    -> where total = (select max(total) from supermarket);+------------+| date       |+------------+| 2019-02-15 |+------------+
We specify the condition in the where clause using another select statement. The nested select statement returns the maximum value of the total column.
We can implement multiple nested select statements. Consider we want to find out how many sales occurred on the date in which the sales with maximum total amount occurred.
This task can be divided into three parts:
Find the maximum total sales amountFind the date of the maximum total sales amountCount the number of sales on this date
Find the maximum total sales amount
Find the date of the maximum total sales amount
Count the number of sales on this date
The following nested query will give us the desired outcome.
mysql> select count(*) from supermarket                # 3    -> where date = (                                  # 2    ->    select date from supermarket     ->    where total = (                              # 1    ->        select max(total) from supermarket ));+----------+| count(*) |+----------+|       19 |+----------+
The dataset contains 3 branches of a supermarket chain. The customers are divided into two categories. We can find the average total sales amount for each cross category of these two columns.
mysql> select branch, cust_type, avg(total)    -> from supermarket    -> group by branch, cust_type    -> order by avg(total) desc;+--------+-----------+------------+| branch | cust_type | avg(total) |+--------+-----------+------------+| C      | Normal    | 337.656604 || C      | Member    | 336.575799 || B      | Member    | 325.483273 || A      | Member    | 321.182455 || B      | Normal    | 314.329341 || A      | Normal    | 303.831792 |+--------+-----------+------------+
The order by clause in the last line sorts the results in descending order based on the averages.
The products are classified into several product lines. We may want to sort the product lines based on the total number of items sold in each category.
mysql> select prod_line, sum(qty)     -> from supermarket    -> group by prod_line    -> order by sum(qty) desc;+----------------------+----------+| prod_line            | sum(qty) |+----------------------+----------+| Electronic accessori |      971 || Food and beverages   |      952 || Sports and travel    |      920 || Home and lifestyle   |      911 || Fashion accessories  |      902 || Health and beauty    |      854 |+----------------------+----------+
It is similar to the previous examples. We select the product line and the sum of quantity columns. The results are grouped by the product line and sorted by the sum of quantities.
We can also implement a combination of aggregate functions in the select statement. For instance, the following query will return the difference between the unit prices of the most expensive and the cheapest items in the health and beauty product line.
mysql> select max(unit_price) - min(unit_price) as diff    -> from supermarket    -> where prod_line = "Health and beauty";+-------+| diff  |+-------+| 89.88 |+-------+
We select the maximum and minimum values of the unit price column and calculate the difference. The “as” keyword is used to assign an alias to the aggregated columns.
If we want to calculate the same difference for each product line, we can omit the where clause and use the group by clause.
mysql> select prod_line, max(unit_price) - min(unit_price) as diff    -> from supermarket    -> group by prod_line;+----------------------+-------+| prod_line            | diff  |+----------------------+-------+| Electronic accessori | 89.17 || Fashion accessories  | 89.71 || Food and beverages   | 89.66 || Health and beauty    | 89.88 || Home and lifestyle   | 89.39 || Sports and travel    | 89.79 |+----------------------+-------+
We have done several examples that demonstrate how SQL can be used as a data analysis tool. It allows for writing queries that can filter, manipulate, and transform the data stored in relational databases.
The main advantage of such queries is that we only retrieve the data we need which can save us a substantial amount of memory. Applying transformations and aggregations on-the-go expedites the data analysis process.
Thank you for reading. Please let me know if you have any feedback.