diff --git a/calculate_largest_expensors.sql b/calculate_largest_expensors.sql index e69de29..4f76e2a 100644 --- a/calculate_largest_expensors.sql +++ b/calculate_largest_expensors.sql @@ -0,0 +1,58 @@ +-- This query identifies employees whose total expenses exceed 1000 and retrieves their information along with their manager's name. +WITH + employees AS ( + SELECT + employee_id, + first_name, + last_name, + manager_id + FROM + EMPLOYEE + ), + expenses AS ( + SELECT + employee_id, + unit_price * quantity AS expensed_amount + FROM + EXPENSE + ), + employees_names AS ( + SELECT + e.employee_id, + CONCAT (e.first_name, ' ', e.last_name) AS employee_name, + e.manager_id + FROM + employees e + ), + employees_with_manager AS ( + SELECT + e.employee_id, + e.employee_name, + e.manager_id, + m.employee_name AS manager_name + FROM + employees_names e + JOIN employees_names m ON e.manager_id = m.employee_id + ), + expense_totals AS ( + SELECT + employee_id, + SUM(expensed_amount) AS total_expensed_amount + FROM + expenses + GROUP BY + employee_id + HAVING + SUM(expensed_amount) > 1000 + ) +SELECT + e.employee_id, + e.employee_name, + e.manager_id, + e.manager_name, + et.total_expensed_amount +FROM + employees_with_manager e + JOIN expense_totals et ON e.employee_id = et.employee_id +ORDER BY + et.total_expensed_amount DESC; \ No newline at end of file diff --git a/create_employees.sql b/create_employees.sql index e69de29..2d7cf56 100644 --- a/create_employees.sql +++ b/create_employees.sql @@ -0,0 +1,32 @@ +USE memory.default; + +DROP TABLE IF EXISTS EMPLOYEE; + +CREATE TABLE + IF NOT EXISTS EMPLOYEE ( + employee_id TINYINT, + first_name VARCHAR, + last_name VARCHAR, + job_title VARCHAR, + manager_id TINYINT + ); + +-- Insert employee data (as provided in hr/employee_index.csv) +INSERT INTO + 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); \ No newline at end of file diff --git a/create_expenses.sql b/create_expenses.sql index e69de29..6e8c262 100644 --- a/create_expenses.sql +++ b/create_expenses.sql @@ -0,0 +1,51 @@ +USE memory.default; + +DROP TABLE IF EXISTS EXPENSE; + +CREATE TABLE IF NOT EXISTS EXPENSE ( + employee_id TINYINT, + -- Employee identifier (mapped from full name) + unit_price DECIMAL(8, 2), + -- Price per unit + quantity TINYINT -- Quantity purchased +); + +-- Insert expense data from receipts (finance/receipts_from_last_night) +INSERT INTO + EXPENSE (employee_id, unit_price, quantity) WITH expenses AS ( + SELECT + * + FROM + ( + VALUES + ('Alex Jacobson', 6.50, 14), + ('Alex Jacobson', 11.00, 20), + ('Alex Jacobson', 22.00, 18), + ('Alex Jacobson', 13.00, 75), + ('Andrea Ghibaudi', 300.00, 1), + ('Darren Poynton', 40.00, 9), + ('Umberto Torrielli', 17.50, 4) + ) AS t (full_name, unit_price, quantity) + ), + employees AS ( + SELECT + employee_id, + CONCAT (first_name, ' ', last_name) AS full_name + FROM + EMPLOYEE + ), + expenses_with_ids AS ( + SELECT + e.employee_id, + ex.unit_price, + ex.quantity + FROM + expenses ex + JOIN employees e ON ex.full_name = e.full_name + ) +SELECT + employee_id, + unit_price, + quantity +FROM + expenses_with_ids; \ No newline at end of file diff --git a/create_invoices.sql b/create_invoices.sql index e69de29..a514089 100644 --- a/create_invoices.sql +++ b/create_invoices.sql @@ -0,0 +1,95 @@ +USE memory.default; + +DROP TABLE IF EXISTS SUPPLIER; + +CREATE TABLE IF NOT EXISTS SUPPLIER ( + supplier_id TINYINT, + -- Unique supplier identifier + name VARCHAR -- Supplier name +); + +INSERT INTO + SUPPLIER (supplier_id, name) WITH supplier_names AS ( + SELECT + * + FROM + ( + VALUES + ('Party Animals'), + ('Catering Plus'), + ('Dave''s Discos'), + ('Entertainment Tonight'), + ('Ice Ice Baby') + ) AS s (name) + ), + supplier_with_id AS ( + SELECT + ROW_NUMBER() OVER ( + ORDER BY + name + ) AS supplier_id, + name + FROM + supplier_names + ) +SELECT + supplier_id, + name +FROM + supplier_with_id; + +DROP TABLE IF EXISTS INVOICE; + +CREATE TABLE IF NOT EXISTS INVOICE ( + supplier_id TINYINT, + invoice_amount DECIMAL(8, 2), + due_date DATE +); + +-- Insert invoice data: map supplier names to supplier_id and calculate due_date +INSERT INTO + INVOICE (supplier_id, invoice_amount, due_date) WITH suppliers AS ( + SELECT + supplier_id, + name + FROM + SUPPLIER + ), + raw_invoices AS ( + -- Raw invoice data from /invoices_due/*.txt: (company_name, invoice_amount, due_months) + SELECT + * + FROM + ( + VALUES + ('Party Animals', 6000.00, 3), + ('Catering Plus', 2000.00, 2), + ('Catering Plus', 1500.00, 3), + ('Dave''s Discos', 500.00, 1), + ('Entertainment Tonight', 6000.00, 3), + ('Ice Ice Baby', 4000.00, 6) + ) AS inv (company_name, invoice_amount, due_months) + ), + invoices_with_ids AS ( + SELECT + s.supplier_id, + inv.invoice_amount, + inv.due_months + FROM + raw_invoices inv + JOIN suppliers s ON inv.company_name = s.name + ), + invoices_with_date AS ( + SELECT + supplier_id, + invoice_amount, + LAST_DAY_OF_MONTH (DATE_ADD ('month', due_months, CURRENT_DATE)) AS due_date + FROM + invoices_with_ids + ) +SELECT + supplier_id, + invoice_amount, + due_date +FROM + invoices_with_date; \ No newline at end of file diff --git a/find_manager_cycles.sql b/find_manager_cycles.sql index e69de29..054caa5 100644 --- a/find_manager_cycles.sql +++ b/find_manager_cycles.sql @@ -0,0 +1,27 @@ +USE memory.default; + +WITH RECURSIVE approval_cycles (employee_id, manager_id, path) AS ( + SELECT + employee_id, + manager_id, + ARRAY[CAST(employee_id AS VARCHAR)] AS path + FROM + EMPLOYEE + UNION ALL + SELECT + ac.employee_id, + m.manager_id, + ac.path || CAST(m.employee_id AS VARCHAR) + FROM + approval_cycles ac + JOIN EMPLOYEE m ON ac.manager_id = m.employee_id + WHERE + NOT contains(ac.path, CAST(m.employee_id AS VARCHAR)) +) +SELECT + employee_id, + path AS cycle +FROM + approval_cycles +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..01f3ca1 100644 --- a/generate_supplier_payment_plans.sql +++ b/generate_supplier_payment_plans.sql @@ -0,0 +1,51 @@ +USE memory.default; + +-- Generate a payment row for each invoice for every payment period. +WITH payment_schedule AS ( + SELECT + i.supplier_id, + last_day_of_month(DATE_ADD('month', offset - 1, CURRENT_DATE)) AS payment_date, + i.invoice_amount / DATE_DIFF('month', CURRENT_DATE, i.due_date) AS monthly_invoice + FROM INVOICE i, + UNNEST(SEQUENCE(1, DATE_DIFF('month', CURRENT_DATE, i.due_date))) AS t(offset) +), +monthly_payment AS ( + SELECT + ps.supplier_id, + sup.name AS supplier_name, + ps.payment_date, + SUM(ps.monthly_invoice) AS payment_amount + FROM payment_schedule ps + JOIN SUPPLIER sup ON ps.supplier_id = sup.supplier_id + GROUP BY ps.supplier_id, sup.name, ps.payment_date +), +total_invoice AS ( + SELECT supplier_id, SUM(invoice_amount) AS total_due + FROM INVOICE + GROUP BY supplier_id +), +final_schedule AS ( + SELECT + mp.supplier_id, + mp.supplier_name, + mp.payment_date, + mp.payment_amount, + GREATEST( + total_due - SUM(mp.payment_amount) OVER ( + PARTITION BY mp.supplier_id + ORDER BY mp.payment_date + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ), + 0 + ) AS balance_to_pay + FROM monthly_payment mp + JOIN total_invoice ti ON mp.supplier_id = ti.supplier_id +) +SELECT + supplier_id, + supplier_name, + payment_amount, + balance_to_pay, + payment_date +FROM final_schedule +ORDER BY supplier_id, payment_date;