diff --git a/calculate_largest_expensors.sql b/calculate_largest_expensors.sql index e69de29..4e4fe3c 100644 --- a/calculate_largest_expensors.sql +++ b/calculate_largest_expensors.sql @@ -0,0 +1,33 @@ +-- Query to report employees who expensed more than 1000 +WITH EmployeeExpenses AS ( + 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 + e.manager_id = m.employee_id + GROUP BY + e.employee_id, e.first_name, e.last_name, e.manager_id, m.first_name, m.last_name +) +SELECT + employee_id, + employee_name, + manager_id, + manager_name, + total_expensed_amount +FROM + EmployeeExpenses +WHERE + total_expensed_amount > 1000 +ORDER BY + total_expensed_amount DESC; \ No newline at end of file diff --git a/create_employees.sql b/create_employees.sql index e69de29..d8a1b2d 100644 --- a/create_employees.sql +++ b/create_employees.sql @@ -0,0 +1,24 @@ +USE MEMORY.DEFAULT; + +-- Create EMPLOYEE table +CREATE TABLE IF NOT EXISTS EMPLOYEE ( + employee_id TINYINT, + first_name VARCHAR, + last_name VARCHAR, + job_title VARCHAR, + manager_id TINYINT +); + +-- Insert data into EMPLOYEE table +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..a38709c 100644 --- a/create_expenses.sql +++ b/create_expenses.sql @@ -0,0 +1,31 @@ +USE MEMORY.DEFAULT; + +-- Create EXPENSE table using a CTE +CREATE TABLE IF NOT EXISTS EXPENSE AS +WITH EXPENSE_WITH_FULL_NAME (employee_full_name, unit_price, quantity) AS ( + VALUES + ('Alex Jacobson', 6.50, 14), + ('Alex Jacobson', 11.00, 20), + ('Alex Jacobson', 22.00, 18), + ('Alex Jacobson', 13.00, 75), + ('Andrea Ghibaudi', 40.00, 9), + ('Andrea Ghibaudi', 17.50, 4) +), +EXPENSE_WITH_ID (employee_id, unit_price, quantity) AS ( + SELECT + EMPLOYEE.employee_id, + CAST(TMP_EXPENSE.unit_price AS DECIMAL(8, 2)) AS unit_price, + CAST(TMP_EXPENSE.quantity AS TINYINT) AS quantity + FROM + EMPLOYEE + INNER JOIN + EXPENSE_WITH_FULL_NAME TMP_EXPENSE + ON + EMPLOYEE.first_name = SPLIT_PART(TMP_EXPENSE.employee_full_name, ' ', 1) + AND EMPLOYEE.last_name = SPLIT_PART(TMP_EXPENSE.employee_full_name, ' ', 2) +) +SELECT + CAST(employee_id AS INT) AS employee_id, + CAST(unit_price AS DECIMAL(8, 2)) AS unit_price, + CAST(quantity AS TINYINT) AS quantity +FROM EXPENSE_WITH_ID; \ No newline at end of file diff --git a/create_invoices.sql b/create_invoices.sql index e69de29..b7fa976 100644 --- a/create_invoices.sql +++ b/create_invoices.sql @@ -0,0 +1,57 @@ +USE MEMORY.DEFAULT; + +-- Create SUPPLIER table +CREATE TABLE IF NOT EXISTS SUPPLIER AS ( + WITH SUPPLIER_NAMES AS ( + SELECT DISTINCT company_name + FROM ( + VALUES + ('Party Animals', 6000, 3), + ('Catering Plus', 2000, 2), + ('Catering Plus', 1500, 3), + ('Dave''s Discos', 500, 1), + ('Entertainment tonight', 6000, 3), + ('Ice Ice Baby', 4000, 6) + ) AS invoices_due(company_name, invoice_amount, due_date) + ), + SUPPLIER_ASSIGNING_IDS_BY_ORDER AS ( + SELECT + ROW_NUMBER() OVER (ORDER BY company_name) AS supplier_id, + company_name + FROM SUPPLIER_NAMES + ) + SELECT + CAST(supplier_id AS TINYINT) AS supplier_id, + CAST(company_name AS VARCHAR) AS name + FROM SUPPLIER_ASSIGNING_IDS_BY_ORDER +); + +-- Create INVOICE table +CREATE TABLE IF NOT EXISTS INVOICE AS ( + WITH INVOICES_DUE (company_name, invoice_amount, invoice_date) AS ( + VALUES + ('Party Animals', 6000, 3), + ('Catering Plus', 2000, 2), + ('Catering Plus', 1500, 3), + ('Dave''s Discos', 500, 1), + ('Entertainment tonight', 6000, 3), + ('Ice Ice Baby', 4000, 6) + ), + INVOICE_WITH_SUPPLIER_IDS AS ( + SELECT + S.supplier_id, + I.invoice_amount, + I.invoice_date + FROM + INVOICES_DUE I + INNER JOIN + SUPPLIER S + ON + I.company_name = S.name + ) + SELECT + CAST(supplier_id AS TINYINT) AS supplier_id, + CAST(invoice_amount AS DECIMAL(8, 2)) AS invoice_amount, + LAST_DAY_OF_MONTH(DATE_ADD('MONTH', invoice_date, CURRENT_DATE)) AS due_date + FROM INVOICE_WITH_SUPPLIER_IDS +); \ No newline at end of file diff --git a/find_manager_cycles.sql b/find_manager_cycles.sql index e69de29..beca2f8 100644 --- a/find_manager_cycles.sql +++ b/find_manager_cycles.sql @@ -0,0 +1,39 @@ +USE MEMORY.DEFAULT; + +-- Recursive CTE to find employee-manager hierarchy loops +WITH RECURSIVE EmployeeHierarchy (employee_id, manager_id, path) AS ( + -- Base case: Start with employees who have a manager + SELECT + employee_id, + manager_id, + ARRAY[CAST(employee_id AS VARCHAR)] AS path + FROM + EMPLOYEE + WHERE + manager_id IS NOT NULL + + UNION ALL + + -- Recursive case + SELECT + eh.employee_id, + e.manager_id, + eh.path || CAST(e.employee_id AS VARCHAR) + FROM + EmployeeHierarchy eh + INNER JOIN + EMPLOYEE e + ON + eh.manager_id = e.employee_id + WHERE + NOT CONTAINS(eh.path, CAST(e.employee_id AS VARCHAR)) +) + +-- Final output +SELECT + employee_id, + ARRAY_JOIN(path, ',') AS loop +FROM + EmployeeHierarchy +WHERE + manager_id = employee_id; \ No newline at end of file diff --git a/generate_supplier_payment_plans.sql b/generate_supplier_payment_plans.sql index e69de29..2c42572 100644 --- a/generate_supplier_payment_plans.sql +++ b/generate_supplier_payment_plans.sql @@ -0,0 +1,68 @@ +WITH SupplierInvoices AS ( + SELECT + s.supplier_id, + s.name AS supplier_name, + SUM(i.invoice_amount) AS total_invoice_amount, + MAX(i.due_date) AS max_due_date + FROM + SUPPLIER s + INNER JOIN + INVOICE i + ON + s.supplier_id = i.supplier_id + GROUP BY + s.supplier_id, s.name +), + +-- Generate payment schedule for each supplier +PaymentSchedule AS ( + SELECT + si.supplier_id, + si.supplier_name, + si.total_invoice_amount, + si.max_due_date, + -- Calculate the number of months until the due date + DATE_DIFF('MONTH', CURRENT_DATE, si.max_due_date) AS months_until_due, + -- Calculate the monthly payment amount (equal installments except the last one) + FLOOR(si.total_invoice_amount / DATE_DIFF('MONTH', CURRENT_DATE, si.max_due_date)) AS monthly_payment_amount, + -- Calculate the remaining amount for the last payment + si.total_invoice_amount - (FLOOR(si.total_invoice_amount / DATE_DIFF('MONTH', CURRENT_DATE, si.max_due_date)) * (DATE_DIFF('MONTH', CURRENT_DATE, si.max_due_date) - 1)) AS final_payment_amount + FROM + SupplierInvoices si +), + +-- Generate payment dates and amounts +Payments AS ( + SELECT + ps.supplier_id, + ps.supplier_name, + ps.total_invoice_amount, + -- Payment amount: equal installments except the last one + CASE + WHEN n.n < ps.months_until_due - 1 THEN ps.monthly_payment_amount + ELSE ps.final_payment_amount + END AS payment_amount, + -- Payment date: end of each month + LAST_DAY_OF_MONTH(DATE_ADD('MONTH', n.n, CURRENT_DATE)) AS payment_date, + -- Balance to pay: total invoice amount minus cumulative payments + ps.total_invoice_amount - SUM(CASE + WHEN n.n < ps.months_until_due - 1 THEN ps.monthly_payment_amount + ELSE ps.final_payment_amount + END) OVER (PARTITION BY ps.supplier_id ORDER BY n.n) AS balance_to_pay + FROM + PaymentSchedule ps + CROSS JOIN + UNNEST(SEQUENCE(0, ps.months_until_due - 1)) AS n(n) +) + +-- Final output +SELECT + supplier_id, + supplier_name, + payment_amount, + balance_to_pay, + payment_date +FROM + Payments +ORDER BY + supplier_id, payment_date; \ No newline at end of file