diff --git a/calculate_largest_expensors.sql b/calculate_largest_expensors.sql index e69de29..ef5c068 100644 --- a/calculate_largest_expensors.sql +++ b/calculate_largest_expensors.sql @@ -0,0 +1,25 @@ +USE memory.default; + +WITH EmployeeExpenses AS ( + SELECT + employee_id, + SUM(unit_price * quantity) AS total_expensed_amount + FROM + memory.default.EXPENSE + GROUP BY + employee_id + HAVING + SUM(unit_price * quantity) > 1000 +) +SELECT + e.employee_id, + e.first_name || ' ' || e.last_name AS employee_name, + e.manager_id, + m.first_name || ' ' || m.last_name AS manager_name, + ee.total_expensed_amount +FROM + memory.default.EMPLOYEE e + JOIN EmployeeExpenses ee ON e.employee_id = ee.employee_id + LEFT JOIN memory.default.EMPLOYEE m ON e.manager_id = m.employee_id +ORDER BY + ee.total_expensed_amount DESC; \ No newline at end of file diff --git a/create_employees.sql b/create_employees.sql index e69de29..d03156c 100644 --- a/create_employees.sql +++ b/create_employees.sql @@ -0,0 +1,24 @@ +USE memory.default; + +-- DROP TABLE memory.default.EMPLOYEE; + +CREATE TABLE memory.default.EMPLOYEE ( + employee_id TINYINT, + first_name VARCHAR, + last_name VARCHAR, + job_title VARCHAR, + manager_id TINYINT +); + +INSERT INTO memory.default.EMPLOYEE (employee_id, first_name, last_name, job_title, manager_id) 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); + + diff --git a/create_expenses.sql b/create_expenses.sql index e69de29..37a4f7b 100644 --- a/create_expenses.sql +++ b/create_expenses.sql @@ -0,0 +1,19 @@ +USE memory.default; + +-- DROP TABLE memory.default.EXPENSE; + +CREATE TABLE memory.default.EXPENSE ( + employee_id TINYINT, + unit_price DECIMAL(8,2), + quantity TINYINT +); + +INSERT INTO memory.default.EXPENSE VALUES +(3,6.50,14), +(3,11.0,22), +(3,22.0,18), +(3,13.00,75), +(9,300.00,1), +(4,40.00,9), +(2,17.50,4); + diff --git a/create_invoices.sql b/create_invoices.sql index e69de29..b658f6e 100644 --- a/create_invoices.sql +++ b/create_invoices.sql @@ -0,0 +1,32 @@ +USE memory.default; + +-- DROP TABLE memory.default.INVOICE; + +CREATE TABLE memory.default.INVOICE ( + supplier_id TINYINT, + invoice_amount DECIMAL(8,2), + due_date DATE +); + +-- DROP TABLE memory.default.SUPPLIER; + + +CREATE TABLE memory.default.SUPPLIER ( + supplier_id TINYINT, + name VARCHAR +); + +INSERT INTO memory.default.SUPPLIER (supplier_id, name) VALUES +(1, 'Catering Plus'), +(2, 'Dave''s Discos'), +(3, 'Entertainment tonight'), +(4, 'Ice Ice Baby'), +(5, 'Party Animals'); + +INSERT INTO memory.default.INVOICE (supplier_id, invoice_amount, due_date) VALUES +(1, 2000.00, DATE '2025-01-31'), +(1, 1500.00, DATE '2025-02-28'), +(2, 500.00, DATE '2024-12-31'), +(3, 6000.00, DATE '2025-02-28'), +(4, 4000.00, DATE '2025-04-30'), +(5, 6000.00, DATE '2025-02-28'); \ No newline at end of file diff --git a/find_manager_cycles.sql b/find_manager_cycles.sql index e69de29..9ed2231 100644 --- a/find_manager_cycles.sql +++ b/find_manager_cycles.sql @@ -0,0 +1,30 @@ +USE memory.default; + +WITH RECURSIVE Hierarchy (employee_id, manager_id, path) AS ( + SELECT + employee_id, + manager_id, + ARRAY[CAST(employee_id AS VARCHAR)] AS path + FROM + memory.default.EMPLOYEE + + UNION ALL + + + SELECT + h.employee_id, + m.manager_id, + h.path || CAST(m.employee_id AS VARCHAR) + FROM + Hierarchy h + JOIN memory.default.EMPLOYEE m ON h.manager_id = m.employee_id + WHERE + NOT contains(h.path, CAST(m.employee_id AS VARCHAR)) +) +SELECT + employee_id, + array_join(path, ' -> ') AS cycle +FROM + Hierarchy +WHERE + contains(path, CAST(manager_id AS VARCHAR)); \ No newline at end of file diff --git a/generate_supplier_payment_plans.sql b/generate_supplier_payment_plans.sql index e69de29..62694c6 100644 --- a/generate_supplier_payment_plans.sql +++ b/generate_supplier_payment_plans.sql @@ -0,0 +1,52 @@ +USE memory.default; + +-- STEPS I TOOK - thought process: +-- 1. Count the number of 'payments' (instalments) for each supplier. +-- 2. Divide all invoices into payments +-- 3. Aggregate payments per supplier for each month +-- 4. Set payment_date (last day of each consecutive month until payment month) +-- 5. Join with SUPPLIER table to get supplier names. +-- 6. Optimise code using CTE to improve readability and reusability + +-- Get data about invoices +WITH invoice_data AS ( + SELECT + supplier_id, + invoice_amount, + due_date, + date_diff('month', current_date, due_date) AS months_until_due, + current_date + FROM memory.default.INVOICE +), -- Generate payment schedule + payment_schedule AS ( + SELECT + supplier_id, + invoice_amount / months_until_due AS monthly_payment, + last_day_of_month(date_add('month', month_index - 1, current_date)) AS payment_date + FROM invoice_data + CROSS JOIN UNNEST(sequence(1, months_until_due)) AS t(month_index) + ), -- Aggregate monthly payments for each supplier + monthly_totals AS ( + SELECT + supplier_id, + payment_date, + SUM(monthly_payment) AS total_monthly_payment, + SUM(SUM(monthly_payment)) OVER (PARTITION BY supplier_id) AS total_amount + FROM payment_schedule + GROUP BY supplier_id, payment_date + ) + +-- Generate balance_outstanding (left to pay after each payment) and join table SUPPLIERS to get supplier names +SELECT + monthly_totals.supplier_id, + suppliers.name AS supplier_name, + monthly_totals.total_monthly_payment AS payment_amount, + GREATEST(monthly_totals.total_amount - SUM(monthly_totals.total_monthly_payment) OVER ( + PARTITION BY monthly_totals.supplier_id + ORDER BY monthly_totals.payment_date + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ), 0) AS balance_outstanding, + monthly_totals.payment_date +FROM monthly_totals + JOIN memory.default.SUPPLIER AS suppliers ON monthly_totals.supplier_id = suppliers.supplier_id +ORDER BY monthly_totals.supplier_id, monthly_totals.payment_date;