From 7dede6c13f9160ecb8c7f9d54cce2448730128c3 Mon Sep 17 00:00:00 2001 From: Krzysztof Dymkowski Date: Thu, 11 Sep 2025 21:51:43 +0200 Subject: [PATCH] Solved ex. --- calculate_largest_expensors.sql | 33 ++++++++++++++ create_employees.sql | 24 ++++++++++ create_expenses.sql | 41 +++++++++++++++++ create_invoices.sql | 68 +++++++++++++++++++++++++++++ find_manager_cycles.sql | 35 +++++++++++++++ generate_supplier_payment_plans.sql | 14 ++++++ 6 files changed, 215 insertions(+) diff --git a/calculate_largest_expensors.sql b/calculate_largest_expensors.sql index e69de29..431e60a 100644 --- a/calculate_largest_expensors.sql +++ b/calculate_largest_expensors.sql @@ -0,0 +1,33 @@ +WITH +employee_expenses AS +( + SELECT employee_id, unit_price * quantity AS expensed_amount + FROM expense +), +total_expenses AS +( + SELECT employee_id, SUM(expensed_amount) AS total_expensed_amount + FROM employee_expenses + GROUP BY employee_id +), +employee_cte +AS +( + SELECT employee_id, manager_id, CONCAT(first_name, ' ', last_name) AS employee_name + FROM employee +), + +manager_cte +AS +( + SELECT employee_id AS manager_id, CONCAT(first_name, ' ', last_name) AS manager_name + FROM employee +) + +SELECT te.employee_id, e.employee_name, e.manager_id, m.manager_name, te.total_expensed_amount +FROM total_expenses AS te +LEFT JOIN employee_cte AS e +ON e.employee_id = te.employee_id +LEFT JOIN manager_cte AS m +ON m.manager_id = e.manager_id +WHERE total_expensed_amount > 1000; \ No newline at end of file diff --git a/create_employees.sql b/create_employees.sql index e69de29..c97f458 100644 --- a/create_employees.sql +++ b/create_employees.sql @@ -0,0 +1,24 @@ +-- When interacting with trino, USE the memory.default catalogue.schema. +USE memory.default; + + +-- load to table using INSERT +CREATE TABLE IF NOT EXISTS employee +AS +SELECT * +FROM ( + 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) +) as t(employee_id, first_name, last_name, job_title, manager_id); + +--2. Set the mxployee_id and manager_id columns to the TINYINT data type. +ALTER TABLE IF EXISTS exployee ALTER COLUMN exployee_id SET DATA TYPE TINYINT; +ALTER TABLE IF EXISTS exployee ALTER COLUMN manager_id SET DATA TYPE TINYINT; \ No newline at end of file diff --git a/create_expenses.sql b/create_expenses.sql index e69de29..ae06171 100644 --- a/create_expenses.sql +++ b/create_expenses.sql @@ -0,0 +1,41 @@ +CREATE TABLE IF NOT EXISTS expense +( + employee_id TINYINT, + unit_price DECIMAL(8, 2), + quantity TINYINT +); + +CREATE OR REPLACE VIEW recipes_cleaned AS + WITH + receipts_from_last_night + AS + ( + SELECT * + FROM ( + VALUES + ('Employee: Alex Jacobson', 'Items: Drinks, lots of drinks', 'Unit Price: 6.50', 'Quantity: 14'), -- drinkies.txt + ('Employee: Alex Jacobson', 'Items: More Drinks', 'Unit Price: 11.00', 'Quantity: 20'), -- drinks.txt + ('Employee: Alex Jacobson', 'Items: So Many Drinks!', 'Unit Price: 22.00', 'Quantity: 18'), -- drinkss.txt + ('Employee: Alex Jacobson', 'Items: I bought everyone in the bar a drink!', 'Unit Price: 13.00', 'Quantity: 75'), -- duh_i_think_i_got_too_many.txt + ('Employee: Andrea Ghibaudi', 'Items: Flights from Mexico back to New York', 'Unit Price: 300', 'Quantity: 1'), -- i_got_lost_on_the_way_home_and_now_im_in_mexico.txt + ('Employee: Darren Poynton', 'Items: Ubers to get us all home', 'Unit Price: 40.00', 'Quantity: 9'), -- ubers.txt + ('Employee: Umberto Torrielli', 'Items: I had too much fun and needed something to eat', 'Unit Price: 17.50', 'Quantity: 4') -- we_stopped_for_a_kebabs.txt + ) AS t(employee, items, unit_price, quantity) + + ), + + receipts_from_last_night_cleaned AS ( + SELECT + split(employee, ': ')[2] AS employee, + CAST(split(unit_price, ': ')[2] AS DECIMAL(8,2)) AS unit_price, + CAST(split(quantity, ': ')[2] AS TINYINT) AS quantity + FROM receipts_from_last_night + ) + SELECT e.employee_id, r.unit_price, r.quantity + FROM receipts_from_last_night_cleaned AS r + LEFT JOIN employee AS e + ON r.employee = e.first_name || ' ' || e.last_name; + +INSERT INTO expense (employee_id, unit_price, quantity) +SELECT employee_id, unit_price, quantity +FROM recipes_cleaned; diff --git a/create_invoices.sql b/create_invoices.sql index e69de29..65174d6 100644 --- a/create_invoices.sql +++ b/create_invoices.sql @@ -0,0 +1,68 @@ + +CREATE TABLE IF NOT EXISTS invoice +( + supplier_id TINYINT, + invoice_amount DECIMAL(8, 2), + due_date DATE +); + +CREATE TABLE IF NOT EXISTS supplier +( + supplier_id TINYINT, + supplier_name VARCHAR +); + + +CREATE OR REPLACE VIEW invoices_cleaned +AS + WITH + invoices_due + AS + (SELECT * + FROM ( + VALUES + ('Invoice', '-------','Company Name: Party Animals', 'Invoice Items: Zebra, Lion, Giraffe, Hippo', 'Invoice Amount: 6000', 'Due Date: 3 months from now'), -- awesome_animals.txt + ('Invoice', '-------', 'Company Name: Catering Plus', 'Invoice Items: Champagne, Whiskey, Vodka, Gin, Rum, Beer, Wine.','Invoice Amount: 2000','Due Date: 2 months from now'), -- brilliant_bottles.txt + ('Invoice', '-------', 'Company Name: Catering Plus', 'Invoice Items: Pizzas, Burgers, Hotdogs, Cauliflour Wings, Caviar', 'Invoice Amount: 1500','Due Date: 3 months from now'), -- crazy_catering.txt + ('Invoice', '-------', 'Company Name: Dave''s Discos', 'Invoice Items: Dave, Dave Equipment', 'Invoice Amount: 500', 'Due Date: 1 month from now'), -- disco_dj.txt + ('Invoice', '-------', 'Company Name: Entertainment tonight', 'Invoice Items: Portable Lazer tag, go carts, virtual darts, virtual shooting, puppies.', 'Invoice Amount: 6000', 'Due Date: 3 months from now'), -- excellent_entertainment.txt + ('Invoice', '-------', 'Company Name: Ice Ice Baby', 'Invoice Items: Ice Luge, Lifesize ice sculpture of Umberto', 'Invoice Amount: 4000', 'Due Date: 6 months from now') + ) as t(header_part_1, header_part_2, company_name, invoice_items,invoice_amount_raw, due_date_raw ) + ), + invoices_due_cleaned AS + ( + SELECT SPLIT(company_name, ': ')[2] AS supplier_name, + CAST(SPLIT(invoice_amount_raw, ': ')[2] AS DECIMAL(8, 2)) AS invoice_amount, + current_date + CAST(regexp_extract(due_date_raw, '([0-9]+)', 1) AS INTEGER) * INTERVAL '1' MONTH AS due_date_raw + FROM invoices_due + ), + + suppliers_raw AS + ( + SELECT DISTINCT supplier_name + FROM invoices_due_cleaned + ), + + suppliers AS + ( + SELECT ROW_NUMBER() OVER (ORDER BY supplier_name ASC) AS supplier_id, supplier_name + FROM suppliers_raw + ) + + SELECT s.supplier_id, + s.supplier_name, + invoice_amount, + date_trunc('month' ,due_date_raw) + interval '1' MONTH - INTERVAL '1' DAY AS due_date + FROM invoices_due_cleaned AS i + LEFT JOIN suppliers AS s + ON s.supplier_name = i.supplier_name; + +TRUNCATE TABLE invoice; +INSERT INTO invoice +SELECT supplier_id, invoice_amount, due_date +FROM invoices_cleaned; + +TRUNCATE TABLE supplier; +INSERT INTO supplier +SELECT DISTINCT supplier_id, supplier_name +FROM invoices_cleaned; \ No newline at end of file diff --git a/find_manager_cycles.sql b/find_manager_cycles.sql index e69de29..756b2d7 100644 --- a/find_manager_cycles.sql +++ b/find_manager_cycles.sql @@ -0,0 +1,35 @@ +WITH RECURSIVE hierarchy(employee_id, manager_id, path) AS ( + -- Start with each employee + SELECT + e.employee_id, + e.manager_id, + ARRAY[e.employee_id] AS path + FROM employee e + + UNION ALL + + -- Walk upward in the manager chain + SELECT + h.employee_id, + e.manager_id, + h.path || e.employee_id + FROM hierarchy h + JOIN employee e + ON h.manager_id = e.employee_id + -- Prevent infinite loops: stop if employee already visited + WHERE NOT contains(h.path, e.employee_id) +), + + +-- A cycle exists when manager_id points back into the path +cycles (employee_id, path) AS ( + SELECT + employee_id, + path + FROM hierarchy + WHERE CONTAINS(path, manager_id) +) +SELECT + employee_id, + array_join(path, ' -> ') AS loop_path +FROM cycles; diff --git a/generate_supplier_payment_plans.sql b/generate_supplier_payment_plans.sql index e69de29..accb88f 100644 --- a/generate_supplier_payment_plans.sql +++ b/generate_supplier_payment_plans.sql @@ -0,0 +1,14 @@ +WITH +payment_amount AS +( + SELECT supplier_id, due_date AS payment_date, SUM(invoice_amount) AS payment_amount + FROM invoice + GROUP BY supplier_id, due_date +) +SELECT pa.supplier_id, s.supplier_name, pa.payment_amount, + SUM(pa.payment_amount) OVER (PARTITION BY pa.supplier_id ORDER BY payment_date DESC) AS balance_outstanding, + pa.payment_date +FROM payment_amount AS pa +LEFT JOIN supplier AS s +ON pa.supplier_id = s.supplier_id +ORDER BY pa.supplier_id ASC ,payment_date ASC; \ No newline at end of file