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
20 changes: 20 additions & 0 deletions calculate_largest_expensors.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
USE memory.default;

-- This query reports employees whose total expensed_amount exceeds 1000.
-- The expensed_amount is computed as unit_price * quantity for each expense.
-- We join the EXPENSE and EMPLOYEE tables and also fetch the manager's name via a self-join.
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(exp.unit_price * exp.quantity) AS total_expensed_amount
FROM EXPENSE exp
JOIN EMPLOYEE e ON exp.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
HAVING SUM(exp.unit_price * exp.quantity) > 1000
ORDER BY total_expensed_amount DESC;

-- Comment: This query aggregates all expenses per employee and filters out those who expensed more than 1000.
25 changes: 25 additions & 0 deletions create_employees.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
USE memory.default;

-- Creating EMPLOYEE table using data from hr/employee_index.csv file
CREATE TABLE EMPLOYEE (
employee_id TINYINT,
first_name VARCHAR,
last_name VARCHAR,
job_title VARCHAR,
manager_id TINYINT
)
COMMENT 'Employee table using data from hr/employee_index.csv file';

-- Inserting data into EMPLOYEE table
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);

-- Comment: Data inserted as per employee_index.csv.
42 changes: 42 additions & 0 deletions create_expenses.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
USE memory.default;

-- Creating EXPENSE table to store last night's receipts.
CREATE TABLE EXPENSE (
employee_id TINYINT,
unit_price DECIMAL(8,2),
quantity TINYINT
)
COMMENT 'Expense table loaded from finance/receipts_from_last_night files';

-- Inserting receipt data from finance/receipts_from_last_night

-- From drinkies.txt:
-- Employee: Alex Jacobson (employee_id: 3), Unit Price: 6.50, Quantity: 14
INSERT INTO EXPENSE VALUES (3, 6.50, 14);

-- From drinks.txt:
-- Employee: Alex Jacobson (employee_id: 3), Unit Price: 11.00, Quantity: 20
INSERT INTO EXPENSE VALUES (3, 11.00, 20);

-- From drinkss.txt:
-- Employee: Alex Jacobson (employee_id: 3), record incomplete (no unit price/quantity provided).
-- We set unit_price and quantity to 0 to indicate missing data.
INSERT INTO EXPENSE VALUES (3, 0.00, 0);

-- From duh_i_think_i_got_too_many.txt:
-- Employee: Alex Jacobson (employee_id: 3), Unit Price: 13.00, Quantity: 75
INSERT INTO EXPENSE VALUES (3, 13.00, 75);

-- From i_got_lost_on_the_way_home_and_now_im_in_mexico.txt:
-- Employee: Andrea Ghibaudi (employee_id: 9), Unit Price: 300, Quantity: 1
INSERT INTO EXPENSE VALUES (9, 300.00, 1);

-- From ubers.txt:
-- Employee: Darren Poynton (employee_id: 4), Unit Price: 40.00, Quantity: 9
INSERT INTO EXPENSE VALUES (4, 40.00, 9);

-- From we_stopped_for_a_kebabs.txt:
-- Employee: Umberto Torrielli (employee_id: 2), Unit Price: 17.50, Quantity: 4
INSERT INTO EXPENSE VALUES (2, 17.50, 4);

-- Comment: Using direct inserts to simulate the imported receipts from text files.
58 changes: 58 additions & 0 deletions create_invoices.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
USE memory.default;

-- Creating the INVOICE table to store supplier invoice details.
CREATE TABLE INVOICE (
supplier_id TINYINT,
invoice_ammount DECIMAL(8,2),
due_date DATE
)
COMMENT 'Invoice table loaded from finance/invoices_due files';

-- Creating the SUPPLIER table to store supplier details.
CREATE TABLE SUPPLIER (
supplier_id TINYINT,
name VARCHAR
)
COMMENT 'Supplier table derived from invoice file company names';

-- Inserting supplier data.
-- Suppliers sorted alphabetically:
-- 1: Catering Plus
-- 2: Dave''s Discos
-- 3: Entertainment tonight
-- 4: Ice Ice Baby
-- 5: Party Animals

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

-- Inserting invoice data from invoice files:
-- awesome_animals.txt:
-- Company Name: Party Animals, Invoice Amount: 6000, Due Date: 3 months from now (assume 2025-07-31)
INSERT INTO INVOICE VALUES (5, 6000.00, DATE '2025-07-31');

-- brilliant_bottles.txt:
-- Company Name: Catering Plus, Invoice Amount: 2000, Due Date: 2 months from now (assume 2025-06-30)
INSERT INTO INVOICE VALUES (1, 2000.00, DATE '2025-06-30');

-- crazy_catering.txt:
-- Company Name: Catering Plus, Invoice Amount: 1500, Due Date: 3 months from now (assume 2025-07-31)
INSERT INTO INVOICE VALUES (1, 1500.00, DATE '2025-07-31');

-- disco_dj.txt:
-- Company Name: Dave's Discos, Invoice Amount: 500, Due Date: 1 month from now (assume 2025-05-31)
INSERT INTO INVOICE VALUES (2, 500.00, DATE '2025-05-31');

-- excellent_entertainment.txt:
-- Company Name: Entertainment tonight, Invoice Amount: 6000, Due Date: 3 months from now (assume 2025-07-31)
INSERT INTO INVOICE VALUES (3, 6000.00, DATE '2025-07-31');

-- fantastic_ice_sculptures.txt:
-- Company Name: Ice Ice Baby, Invoice Amount: 4000, Due Date: 6 months from now (assume 2025-10-31)
INSERT INTO INVOICE VALUES (4, 4000.00, DATE '2025-10-31');

-- Comment: Due dates set to the last day of the respective month based on "n months from now".
31 changes: 31 additions & 0 deletions find_manager_cycles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
USE memory.default;

-- This query attempts to detect cycles in the manager relationships (i.e., employees approving each other's expenses).
-- We use a recursive Common Table Expression (CTE) to build paths from each employee up the management chain.
-- The resulting path is returned as a comma-separated list of employee_ids indicating the cycle.
WITH RECURSIVE manager_paths(employee_id, manager_id, path) AS (
-- Base step: start with each employee
SELECT
employee_id,
manager_id,
CAST(employee_id AS VARCHAR) AS path
FROM EMPLOYEE
UNION ALL
-- Recursive step: join with EMPLOYEE to follow the manager chain
SELECT
mp.employee_id,
e.manager_id,
CONCAT(mp.path, ',', CAST(e.manager_id AS VARCHAR))
FROM manager_paths mp
JOIN EMPLOYEE e ON mp.manager_id = e.employee_id
-- Prevent cycles from repeating nodes in the path
WHERE strpos(mp.path, CAST(e.manager_id AS VARCHAR)) = 0
)
-- Select paths where the cycle is closed; for instance, where the current manager_id appears in the path.
SELECT
employee_id,
path AS manager_cycle
FROM manager_paths
WHERE strpos(path, CAST(manager_id AS VARCHAR)) > 0;

-- Comment: This recursive CTE builds the chain and then filters for cycles.
44 changes: 44 additions & 0 deletions generate_supplier_payment_plans.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
USE memory.default;

-- Generate a monthly supplier payment plan.
-- For each supplier, we assume a fixed maximum monthly payment of 1500.
-- The total number of payments is calculated as CEIL(total_outstanding / 1500).
-- Payment dates are generated by adding an offset in months to the end-of-current-month date.
-- This approach uses UNNEST and sequence() to simulate the recurrence without a recursive CTE.

WITH supplier_totals AS (
-- Calculate total outstanding per supplier from all invoices
SELECT
s.supplier_id,
s.name AS supplier_name,
SUM(i.invoice_ammount) AS total_outstanding
FROM SUPPLIER s
JOIN INVOICE i ON s.supplier_id = i.supplier_id
GROUP BY s.supplier_id, s.name
),
supplier_payments AS (
SELECT
supplier_id,
supplier_name,
total_outstanding,
CAST(CEIL(total_outstanding / 1500.0) AS INTEGER) AS num_payments
FROM supplier_totals
)
SELECT
sp.supplier_id,
sp.supplier_name,
-- Determine payment amount: For all but the last payment, it's 1500, otherwise the remaining balance.
CASE
WHEN month_offset < sp.num_payments - 1 THEN 1500.00
ELSE sp.total_outstanding - 1500.00 * (sp.num_payments - 1)
END AS payment_amount,
-- Calculate the remaining balance after the payment at this step
sp.total_outstanding - 1500.00 * month_offset AS balance_outstanding,
-- Payment date: start at the end of the current month and add month_offset months
CAST(date_add('month', month_offset,
CAST(date_trunc('month', CURRENT_DATE) + interval '1' month - interval '1' day AS DATE))
AS DATE) AS payment_date
FROM supplier_payments sp,
-- Generate a series [0, num_payments-1] per supplier to represent each payment.
UNNEST(sequence(0, sp.num_payments - 1)) AS t(month_offset)
ORDER BY sp.supplier_id, payment_date;