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


-- Aggregate total expensed amount per employee

WITH total_expensed_amount AS (
SELECT
employee_id,
SUM(unit_price * quantity) AS total_expensed
FROM expense
GROUP BY employee_id
)

-- List employees whose total expenses exceed the threshold
SELECT
e.employee_id,
e.first_name || ' ' || e.last_name AS employee_name,
tea.total_expensed,
e.manager_id,
m.first_name || ' ' || m.last_name AS manager_name
FROM total_expensed_amount tea
JOIN employee e
ON e.employee_id = tea.employee_id
LEFT JOIN employee m
ON e.manager_id = m.employee_id -- manager information when available
WHERE tea.total_expensed > 1000 -- threshold
ORDER BY tea.total_expensed DESC;
22 changes: 22 additions & 0 deletions create_employees.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
USE memory.default;


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


-- Since the Trino CLI does not support direct CSV ingestion, the data has been converted into explicit INSERT statements.
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);
16 changes: 16 additions & 0 deletions create_expenses.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
USE memory.default;

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


INSERT INTO expense (employee_id,unit_price, quantity) VALUES
(3, 6.5, 14),
(3, 11, 20),
(3, 22, 18),
(3, 13, 75),
(9, 300, 1),
(4, 40, 9),
(2, 17.5, 4);
33 changes: 33 additions & 0 deletions create_invoices.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
USE memory.default;

-- Raw staging table for incoming invoice data, corrected typo invoice_ammount
CREATE TABLE IF NOT EXISTS invoice_raw (
supplier_name VARCHAR,
invoice_amount DECIMAL(8,2),
due_date DATE);

INSERT INTO invoice_raw (supplier_name, invoice_amount, due_date) VALUES
('Party Animals', 6000, last_day_of_month(date_add('month', 3, DATE '2026-02-02'))),
('Catering Plus', 2000, last_day_of_month(date_add('month', 2, DATE '2026-02-02'))),
('Catering Plus', 1500, last_day_of_month(date_add('month', 3, DATE '2026-02-02'))),
('Daves Discos', 500, last_day_of_month(date_add('month', 1, DATE '2026-02-02'))),
('Entertainment tonight', 6000, last_day_of_month(date_add('month', 3, DATE '2026-02-02'))),
('Ice Ice Baby', 4000, last_day_of_month(date_add('month', 6, DATE '2026-02-02')));


-- One row per supplier, with deterministic IDs assigned alphabetically by supplier name.
CREATE TABLE IF NOT EXISTS supplier as (
SELECT
CAST(ROW_NUMBER() OVER (ORDER BY supplier_name)as TINYINT) as supplier_id,
supplier_name as name
FROM invoice_raw
GROUP BY supplier_name);

-- Final invoice table with corrected typo invoice_ammount
CREATE TABLE IF NOT EXISTS invoice as(
SELECT s.supplier_id,
i.invoice_amount,
i.due_date
FROM invoice_raw i
JOIN supplier s
ON i.supplier_name = s.name);
66 changes: 66 additions & 0 deletions find_manager_cycles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
USE memory.default;


CREATE TABLE emp_paths AS
WITH RECURSIVE paths (root_id, employee_id, manager_id, visited, depth) AS (

-- Start: one path per employee

SELECT
e.employee_id AS root_id,
e.employee_id,
e.manager_id,
ARRAY[e.employee_id] AS visited,
1 AS depth
FROM employee e

UNION ALL

-- Step: move to manager, stop before revisiting a node

SELECT
p.root_id,
m.employee_id,
m.manager_id,
p.visited || m.employee_id,
p.depth + 1
FROM paths p
JOIN employee m
ON m.employee_id = p.manager_id
WHERE p.depth < 10
AND NOT contains(p.visited, m.employee_id)
)
SELECT *
FROM paths;


-- Identify paths where the next manager would close a loop

CREATE TABLE cycle_hits AS
SELECT
p.root_id,
p.manager_id AS loop_member,
p.visited
FROM emp_paths p
WHERE p.manager_id IS NOT NULL
AND contains(p.visited, p.manager_id);


-- Extract the actual cycle as a closed array

CREATE TABLE cycles AS
SELECT
loop_member AS cycle_anchor,
slice(
visited,
array_position(visited, loop_member),
cardinality(visited) - array_position(visited, loop_member) + 1
) || loop_member AS loopcycle
FROM cycle_hits;


-- Final result: one row per detected cycle

SELECT DISTINCT cycle_anchor, loopcycle
FROM cycles
ORDER BY cycle_anchor, loopcycle;
97 changes: 97 additions & 0 deletions generate_supplier_payment_plans.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
USE memory.default;


WITH months as (
-- For each invoice, compute how many end-of-month payments are needed
SELECT
supplier_id,
invoice_amount,
due_date,
date_diff('month', last_day_of_month(DATE '2026-02-02'), due_date) + 1 AS months_to_pay
FROM invoice
),

monthly_rates as (
-- Uniform monthly rate per invoice (invoice amount spread across months_to_pay)
SELECT
supplier_id,
invoice_amount,
due_date,
months_to_pay,
ROUND(invoice_amount/months_to_pay, 2) as rate_amount
FROM months
),

invoice_payment_schedule as (
-- Month offsets per invoice
SELECT
supplier_id,
invoice_amount,
due_date,
months_to_pay,
rate_amount,
sequence(0, months_to_pay - 1) AS month_offsets
FROM monthly_rates
),

invoice_payment_schedule_exploded as (
-- One row per invoice per month payment
SELECT
supplier_id,
invoice_amount,
due_date,
months_to_pay,
rate_amount,
month_index
FROM invoice_payment_schedule
CROSS JOIN UNNEST (month_offsets) AS t(month_index)
),

invoice_payment_calendar AS (
-- Convert offsets into actual end-of-month payment dates
SELECT
supplier_id,
invoice_amount,
rate_amount,
last_day_of_month(date_add('month',month_index,last_day_of_month(DATE '2026-02-02'))) AS payment_date
FROM invoice_payment_schedule_exploded
),

supplier_payment_amount as (
-- Suppliers receive a single aggregated payment per month across all their invoices
SELECT
supplier_id,
SUM(rate_amount) as payment_amount,
payment_date

FROM invoice_payment_calendar
GROUP BY supplier_id, payment_date
),

monthly_plan AS (
-- Compute remaining balance after each monthly payment
SELECT
spa.supplier_id,
s.name AS supplier_name,
spa.payment_amount,
ROUND(
SUM(spa.payment_amount) OVER (PARTITION BY spa.supplier_id)
- SUM(spa.payment_amount) OVER (
PARTITION BY spa.supplier_id
ORDER BY spa.payment_date
),
2
) AS balance_outstanding,
spa.payment_date
FROM supplier_payment_amount spa
JOIN supplier s
ON s.supplier_id = spa.supplier_id
)
SELECT
supplier_id,
supplier_name,
CAST(payment_amount AS DECIMAL (18,2)) as payment_amount,
CAST(balance_outstanding AS DECIMAL (18,2)) as balance_outstanding,
payment_date
FROM monthly_plan
ORDER BY supplier_id, payment_date;