In this article, we will go through an SQL interview problem that requires analyzing a table of incoming transactions. The goal is to calculate the total number of transactions, total amount, and the number of approved transactions and their respective total amount for each month and country. Let’s break down the problem step by step, and I'll guide you through the solution.
Problem Overview:
You are provided with a table called Transactions
, which contains the following columns:
id (int): Unique identifier for each transaction (Primary Key).
country (varchar): The country where the transaction occurred.
state (enum): The status of the transaction (either 'approved' or 'declined').
amount (int): The transaction amount.
trans_date (date): The date when the transaction occurred.
The problem asks us to:
Find the number of transactions and their total amount for each month and country.
Additionally, for each month and country, find the number of approved transactions and their total amount.
You should return these results in any order.
Example:
Input Table:
id | country | state | amount | trans_date |
1 | USA | approved | 100 | 2021-01-01 |
2 | USA | declined | 50 | 2021-01-02 |
3 | USA | approved | 200 | 2021-01-15 |
4 | India | approved | 150 | 2021-01-10 |
5 | India | declined | 60 | 2021-02-01 |
6 | USA | approved | 120 | 2021-02-15 |
7 | India | approved | 200 | 2021-02-17 |
Desired Output:
country | trans_month | total_transactions | total_amount | approved_transactions | approved_amount |
USA | 2021-01 | 3 | 500 | 2 | 300 |
USA | 2021-02 | 2 | 240 | 2 | 240 |
India | 2021-01 | 2 | 300 | 2 | 300 |
India | 2021-02 | 2 | 260 | 1 | 200 |
SQL Schema
Create table If Not Exists Transactions
(id int, country varchar(4), state enum('approved', 'declined'), amount int, trans_date date)
Truncate table Transactions
insert into Transactions (id, country, state, amount, trans_date) values ('121', 'US', 'approved', '1000', '2018-12-18')
insert into Transactions (id, country, state, amount, trans_date) values ('122', 'US', 'declined', '2000', '2018-12-19')
insert into Transactions (id, country, state, amount, trans_date) values ('123', 'US', 'approved', '2000', '2019-01-01')
insert into Transactions (id, country, state, amount, trans_date) values ('124', 'DE', 'approved', '2000', '2019-01-07')
Step-by-Step Solution:
To solve this problem, we need to:
Group the transactions by month and country.
Count the number of total transactions and the sum of total amounts for each group.
Additionally, count the number of approved transactions and their corresponding sum of amounts.
The key here is to extract the year and month from the trans_date
column, which will help us group the data properly.
We can achieve this by using the following SQL query:
SQL Query:
SELECT
country,
DATE_FORMAT(trans_date, '%Y-%m') AS trans_month,
COUNT(*) AS total_transactions, -- Total number of transactions for each month and country
SUM(amount) AS total_amount, -- Total amount of transactions for each month and country
SUM(CASE WHEN state = 'approved' THEN 1 ELSE 0 END) AS approved_transactions, -- Count of approved transactions
SUM(CASE WHEN state = 'approved' THEN amount ELSE 0 END) AS approved_amount -- Total amount of approved transactions
FROM
Transactions
GROUP BY
country,
trans_month
ORDER BY
country,
trans_month;
Explanation:
DATE_FORMAT(trans_date, '%Y-%m'):
- This part formats the
trans_date
column to show only the year and month (YYYY-MM
). This is important for grouping the results by month and country.
- This part formats the
COUNT(*) AS total_transactions:
- This counts the total number of transactions for each group (i.e., for each combination of month and country).
SUM(amount) AS total_amount:
- This calculates the total transaction amount for each group (month and country).
SUM(CASE WHEN state = 'approved' THEN 1 ELSE 0 END) AS approved_transactions:
- The
CASE
statement checks if the transaction state is 'approved'. If it is, it returns1
, otherwise0
. TheSUM
function then calculates the total number of approved transactions by summing these1
s.
- The
SUM(CASE WHEN state = 'approved' THEN amount ELSE 0 END) AS approved_amount:
- Similar to the previous
CASE
statement, this checks if the state is 'approved' and, if so, sums theamount
. This gives the total amount for approved transactions.
- Similar to the previous
GROUP BY country, trans_month:
- This groups the result set by both country and the formatted trans_month, ensuring that the counts and sums are calculated per country and month.
ORDER BY country, trans_month:
- Finally, we order the results by country and transaction month. This step is optional, as the problem specifies the output can be in any order, but it makes the output more readable.
Sample Output:
For the sample input data:
id | country | state | amount | trans_date |
1 | USA | approved | 100 | 2021-01-01 |
2 | USA | declined | 50 | 2021-01-02 |
3 | USA | approved | 200 | 2021-01-15 |
4 | India | approved | 150 | 2021-01-10 |
5 | India | declined | 60 | 2021-02-01 |
6 | USA | approved | 120 | 2021-02-15 |
7 | India | approved | 200 | 2021-02-17 |
The query will return the following result:
country | trans_month | total_transactions | total_amount | approved_transactions | approved_amount |
USA | 2021-01 | 3 | 500 | 2 | 300 |
USA | 2021-02 | 2 | 240 | 2 | 240 |
India | 2021-01 | 2 | 300 | 2 | 300 |
India | 2021-02 | 2 | 260 | 1 | 200 |
Key Takeaways:
Date formatting (
DATE_FORMAT()
or similar functions) is crucial when grouping by month and year.Using conditional aggregation with
CASE
helps in counting and summing only the relevant rows (e.g., only "approved" transactions).Grouping by multiple columns (e.g., country and month) is an essential step when working with date and category-based data.
This solution showcases how to handle various types of aggregations (counting, summing) based on different conditions, which is a common SQL task in real-world scenarios.
I hope this article helps you in understanding how to approach SQL queries involving grouping, aggregation, and conditional logic. Happy querying!