SQL Interview Prep - Day 5

Monthly Transactions

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:

idcountrystateamounttrans_date
1USAapproved1002021-01-01
2USAdeclined502021-01-02
3USAapproved2002021-01-15
4Indiaapproved1502021-01-10
5Indiadeclined602021-02-01
6USAapproved1202021-02-15
7Indiaapproved2002021-02-17

Desired Output:

countrytrans_monthtotal_transactionstotal_amountapproved_transactionsapproved_amount
USA2021-0135002300
USA2021-0222402240
India2021-0123002300
India2021-0222601200

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:

  1. Group the transactions by month and country.

  2. Count the number of total transactions and the sum of total amounts for each group.

  3. 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:

  1. 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.
  2. COUNT(*) AS total_transactions:

    • This counts the total number of transactions for each group (i.e., for each combination of month and country).
  3. SUM(amount) AS total_amount:

    • This calculates the total transaction amount for each group (month and country).
  4. 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 returns 1, otherwise 0. The SUM function then calculates the total number of approved transactions by summing these 1s.
  5. 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 the amount. This gives the total amount for approved transactions.
  6. 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.
  7. 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:

idcountrystateamounttrans_date
1USAapproved1002021-01-01
2USAdeclined502021-01-02
3USAapproved2002021-01-15
4Indiaapproved1502021-01-10
5Indiadeclined602021-02-01
6USAapproved1202021-02-15
7Indiaapproved2002021-02-17

The query will return the following result:

countrytrans_monthtotal_transactionstotal_amountapproved_transactionsapproved_amount
USA2021-0135002300
USA2021-0222402240
India2021-0123002300
India2021-0222601200

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!