Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions calculate_largest_expensors.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
USE memory.default

SELECT
e.employee_id
,CONCAT (e.first_name,' ',e.last_name) AS employee_name
,e.manager_id
,CONCAT (m.first_name,' ',m.last_name) AS manager_name
,SUM(ex.unit_price * ex.quantity) AS total_expensed_amount
FROM EXPENSE ex
INNER JOIN EMPLOYEE e ON ex.employee_id = e.employee_id
LEFT JOIN EMPLOYEE m ON m.employee_id = e.manager_id
GROUP BY e.employee_id
,e.first_name
,e.last_name
,e.manager_id
,m.first_name
,m.last_name
HAVING SUM(ex.unit_price * ex.quantity) > 1000
ORDER BY total_expensed_amount DESC;
21 changes: 21 additions & 0 deletions create_employees.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
USE memory.default;

CREATE TABLE IF NOT EXISTS EMPLOYEE (
employee_id TINYINT,
first_name VARCHAR,
last_name VARCHAR,
job_title VARCHAR,
manager_id TINYINT
);

-- load the initial data from employee_index.csv
INSERT INTO EMPLOYEE VALUES
(1, 'Ian', 'James', 'CEO', 4),
(2, 'Umberto', 'Torrielli', 'CSO', 1),
(3, 'Alex', 'Jacobson', 'MD EMEA', 2),
(4, 'Darren', 'Poynton', 'CFO', 2),
(5, 'Tim', 'Beard', 'MD APAC', 2),
(6, 'Gemma', 'Dodd', 'COS', 1),
(7, 'Lisa', 'Platten', 'CHR', 6),
(8, 'Stefano', 'Camisaca', 'GM Activation', 2),
(9, 'Andrea', 'Ghibaudi', 'MD NAM', 2);
17 changes: 17 additions & 0 deletions create_expenses.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
USE memory.default;

CREATE TABLE IF NOT EXISTS EXPENSE (
employee_id TINYINT,
unit_price DECIMAL(8, 2),
quantity TINYINT
);

-- load the initial data from receipts from last night
INSERT INTO EXPENSE VALUES
(3, 6.50, 14),
(3, 11.00, 20),
(3, 22.00, 18),
(3, 13.00, 75),
(9, 300.00, 1),
(4, 40.00, 9),
(2, 17.50, 4);
30 changes: 30 additions & 0 deletions create_invoices.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
USE memory.default;

CREATE TABLE IF NOT EXISTS SUPPLIER (
supplier_id TINYINT,
name VARCHAR
);

CREATE TABLE IF NOT EXISTS INVOICE (
supplier_id TINYINT,
invoice_amount DECIMAL(8, 2),
due_date DATE
);

INSERT INTO SUPPLIER VALUES
(1, 'Catering Plus'),
(2, 'Dave''s Discos'),
(3, 'Entertainment tonight'),
(4, 'Ice Ice Baby'),
(5, 'Party Animals');

-- I used current date to figure out the due date, in the real world we would probably
-- never do something like this because if the data gets reloaded at some point, the
-- whole payment scheduled would turn to mess
INSERT INTO INVOICE VALUES
(5, 6000.00, LAST_DAY_OF_MONTH(DATE_ADD('month', 3, CURRENT_DATE))),
(1, 2000.00, LAST_DAY_OF_MONTH(DATE_ADD('month', 2, CURRENT_DATE))),
(1, 1500.00, LAST_DAY_OF_MONTH(DATE_ADD('month', 3, CURRENT_DATE))),
(2, 500.00, LAST_DAY_OF_MONTH(DATE_ADD('month', 1, CURRENT_DATE))),
(3, 6000.00, LAST_DAY_OF_MONTH(DATE_ADD('month', 3, CURRENT_DATE))),
(4, 4000.00, LAST_DAY_OF_MONTH(DATE_ADD('month', 6, CURRENT_DATE)));
32 changes: 32 additions & 0 deletions find_manager_cycles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
USE memory.default

WITH RECURSIVE employee_manager (
employee_id
,manager_id
,loop
)
AS (
-- base query, selects all employees
SELECT employee_id
,manager_id
,ARRAY [employee_id] AS loop
FROM EMPLOYEE

UNION ALL

-- recursive query, continuously joins to the base query
SELECT em.employee_id
,e.manager_id
,em.loop || e.employee_id
FROM employee_manager em
INNER JOIN EMPLOYEE e ON em.manager_id = e.employee_id
WHERE NOT CONTAINS (
em.loop
,e.employee_id
) -- breaks the recursion, makes sure that the employee is not already in the loop
)
-- final result, selects only those employees who are a part of the cycle
SELECT employee_id
,loop
FROM employee_manager
WHERE manager_id = employee_id;
70 changes: 70 additions & 0 deletions generate_supplier_payment_plans.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
USE memory.default

------------------------------
/*
This SQL file displays payment plans for each of the suppliers. It consists of three
CTEs.
supplier_invoice finds the latest due date per supplier and calculates the sum of all
invoices for each of them.
monthly_payment_amount calculates number of monthly payments remaining based off the
latest due date. It also calculates monthly payment amount and the last month amount
(monthly payment plus the remainder).
balance generates a sequence (extra rows) for each of the months we have until due
date to cover our expenses. It also displays balance left for each month.

The query was formatted using https://poorsql.com/ formatter.
*/
------------------------------

WITH supplier_invoice
AS (
SELECT s.supplier_id
,s.name AS supplier_name
,SUM(i.invoice_amount) AS total_invoice_amount
,MAX(i.due_date) latest_due_date
FROM INVOICE i
LEFT JOIN SUPPLIER s ON i.supplier_id = s.supplier_id
GROUP BY s.supplier_id
,s.name
),
monthly_payment_amount
AS (
SELECT supplier_id
,supplier_name
,total_invoice_amount
,latest_due_date
,DATE_DIFF('month', CURRENT_DATE, latest_due_date) + 1 AS number_of_payments -- added +1 because we want to start payments at the end of the current month, this creates that extra month for payment
,FLOOR(total_invoice_amount / (DATE_DIFF('month', CURRENT_DATE, latest_due_date) + 1)) AS monthly_amount -- total amount divided by number of months to pay rounded to nearest integer
,total_invoice_amount % (DATE_DIFF('month', CURRENT_DATE, latest_due_date) + 1) AS last_month_remainder -- remainder from the monthly amount, to be added for the last month of payment
FROM supplier_invoice
),
balance
AS (
SELECT supplier_id
,supplier_name
,CASE
WHEN seq < number_of_payments - 1
THEN monthly_amount
ELSE last_month_remainder + monthly_amount
END AS payment_amount -- these are monthly payments which are all the same except last one that includes the remainder
,seq
,total_invoice_amount - sum(CASE
WHEN seq < number_of_payments - 1
THEN monthly_amount
ELSE last_month_remainder + monthly_amount
END) OVER (
PARTITION BY supplier_id ORDER BY seq
) AS balance_outstanding -- calculates the balance remaining
,
LAST_DAY_OF_MONTH(date_add('month', seq, CURRENT_DATE)) AS payment_date
FROM monthly_payment_amount
CROSS JOIN UNNEST(sequence(0, number_of_payments - 1)) AS t(seq) -- generating a sequence of months for each supplier based on the latest due date
)
SELECT supplier_id
,supplier_name
,payment_amount
,balance_outstanding
,payment_date
FROM balance
ORDER BY supplier_id
,payment_date;