set serveroutput on size 32000 -- show errors; -- Question 1: Retailer detail create or replace procedure RetailerDetail (id IN Retailers.RetailerId%TYPE) as retailer_id Retailers.RetailerId%TYPE; retailer_name Retailers.RetailerName%TYPE; retailer_address Retailers.Address%TYPE; retailer_orders Orders.Count%TYPE; retailer_bestseller_id Products.ProductId%TYPE; retailer_bestseller Products.ProductName%TYPE; retailer_bestseller_count Orders.Count%TYPE; -- CURSOR retailer_cursor IS SELECT RetailerId FROM Retailers WHERE RetailerId=id; -- retailer_entry retailer_cursor%ROWTYPE; CURSOR order_cursor IS SELECT Count, OrderId FROM Orders WHERE RetailerId=id; order_entry order_cursor%ROWTYPE; BEGIN SELECT RetailerName INTO retailer_name FROM Retailer WHERE RetailerId=id; SELECT Address INTO retailer_address FROM Retailer WHERE RetailerId=id; SELECT COUNT(OrderId) INTO retailer_orders FROM Orders WHERE RetailerId=id; SELECT ProductId INTO retailer_bestseller_id FROM ( SELECT ProductId, RANK() OVER (ORDER BY Total DESC) AS Score FROM ( SELECT ProductId, SUM(Count) AS Total FROM Orders O WHERE RetailerId=id GROUP BY ProductId ) ) WHERE Score = 1 GROUP BY ProductId; SELECT ProductName INTO retailer_bestseller FROM Products WHERE ProductId=retailer_bestseller_id; SELECT SUM(Count) INTO retailer_bestseller_count FROM Orders WHERE ProductId=retailer_bestseller_id AND RetailerId=id; dbms_output.put_line('Retailer Name: ' || retailer_name); dbms_output.put_line('Retailer Address: ' || retailer_address); dbms_output.put_line('Retailer Total Orders: ' || retailer_orders); dbms_output.put_line('Most Popular Product: ' || retailer_bestseller); dbms_output.put_line('Total Sold: ' || retailer_bestseller_count); END RetailerDetail; / -- show error procedure RetailerDetail; -- make test cases yourselves BEGIN RetailerDetail(1); -- Inferno, 115 RetailerDetail(2); -- Macbook, 12 RetailerDetail(3); -- Nike sports jacket, 3 RetailerDetail(4); -- OnePlus 5t, 1 RetailerDetail(5); -- Pixel Book, 1 end; / -- Queation 2: Monthly delay report create or replace procedure MonthlyDelayReport as order_date VARCHAR(32); order_count Orders.Count%TYPE; order_year VARCHAR(32); order_month VARCHAR(32); retailer_name Retailers.RetailerName%TYPE; CURSOR c_month IS SELECT Year, Month, Total FROM ( SELECT Year, Month, COUNT(OrderId) AS Total FROM ( -- EXTRACT SELECT EXTRACT(YEAR FROM OrderDate) AS Year, EXTRACT(MONTH FROM OrderDate) AS Month, OrderId, Status FROM Orders ) WHERE Status = 'DELAYED' GROUP BY Year, Month ORDER BY Year ASC, Month ASC ) WHERE Total > 0; CURSOR c_retailer IS SELECT DISTINCT R.RetailerName INTO retailer_name FROM ( SELECT RetailerId FROM Orders WHERE EXTRACT(YEAR FROM OrderDate) = order_year AND EXTRACT(MONTH FROM OrderDate) = order_month AND Status = 'DELAYED' ) K, Retailers R WHERE R.RetailerId = K.RetailerId ORDER BY R.RetailerName ASC; BEGIN OPEN c_month; LOOP FETCH c_month INTO order_year, order_month, order_count; EXIT WHEN c_month%NOTFOUND; dbms_output.put_line('Delayed orders in ' || order_year || '-' || order_month || ': ' || order_count); dbms_output.put_line('Retailers with delayed orders:'); OPEN c_retailer; LOOP FETCH c_retailer INTO retailer_name; EXIT WHEN c_retailer%NOTFOUND; dbms_output.put_line('- ' || retailer_name); END LOOP; CLOSE c_retailer; END LOOP; CLOSE c_month; END MonthlyDelayReport; / -- show error procedure MonthlyDelayReport; BEGIN MonthlyDelayReport; End; / -- Question 3: Find the product with least profit in each category create or replace procedure LeastProfitProduct as product_category Products.Category%TYPE; product_name Products.ProductName%TYPE; product_profit Products.ExfactoryPrice%TYPE; CURSOR c_profit IS SELECT ProductName, AverageProfit FROM ( SELECT P.ProductName, AverageProfit, RANK() OVER (ORDER BY AverageProfit ASC) AS Score FROM ( SELECT ProductId, AVG(ProfitMargin) AS AverageProfit FROM ( SELECT O.OrderId, O.ProductId, O.UnitPrice - P.ExFactoryPrice AS ProfitMargin FROM Orders O, Products P WHERE O.ProductId = P.ProductId AND P.Category = product_category ) GROUP BY ProductId ) K, Products P WHERE K.ProductId = P.ProductId ORDER BY AverageProfit DESC, P.ProductName ASC ) WHERE Score = 1; CURSOR c_category IS SELECT DISTINCT Category FROM Products; BEGIN OPEN c_category; LOOP FETCH c_category INTO product_category; EXIT WHEN c_category%NOTFOUND; dbms_output.put_line('Least Profit in ' || product_category); OPEN c_profit; LOOP FETCH c_profit INTO product_name, product_profit; EXIT WHEN c_profit%NOTFOUND; dbms_output.put_line('- ' || product_name || ': ' || product_profit); END LOOP; CLOSE c_profit; END LOOP; CLOSE c_category; END LeastProfitProduct; / BEGIN LeastProfitProduct; END; / -- Queation 4: New table for retailer product category distribution create table RetailerCatergoryTable(RetailerId integer, Electronic integer, Apparel integer, Books integer, primary key(RetailerId)); create or replace procedure RetailerProductCatergory as product_category Products.Category%TYPE; retailer_id Retailers.RetailerId%TYPE; total_electronic integer; total_apparel integer; total_books integer; CURSOR c_retailer IS SELECT RetailerId FROM Retailers; CURSOR c_category IS SELECT COUNT(OrderId) AS Total FROM Orders O, Products P WHERE O.ProductId = P.ProductId AND P.Category = product_category AND O.RetailerId = retailer_id; BEGIN OPEN c_retailer; LOOP FETCH c_retailer INTO retailer_id; EXIT WHEN c_retailer%NOTFOUND; product_category := 'electronics'; SELECT COUNT(OrderId) INTO total_electronic FROM Orders O, Products P WHERE O.ProductId = P.ProductId AND P.Category = product_category AND O.RetailerId = retailer_id; product_category := 'apparel'; SELECT COUNT(OrderId) INTO total_apparel FROM Orders O, Products P WHERE O.ProductId = P.ProductId AND P.Category = product_category AND O.RetailerId = retailer_id; product_category := 'books'; SELECT COUNT(OrderId) INTO total_books FROM Orders O, Products P WHERE O.ProductId = P.ProductId AND P.Category = product_category AND O.RetailerId = retailer_id; INSERT INTO RetailerCatergoryTable (RetailerId, Electronic, Apparel, Books) VALUES (retailer_id, total_electronic, total_apparel, total_books); END LOOP; CLOSE c_retailer; END RetailerProductCatergory; / -- show error procedure RetailerProductCatergory; BEGIN RetailerProductCatergory; END; / select * from RetailerCatergoryTable; drop table RetailerCatergoryTable; -- Question 5: Exception Handle create or replace procedure CustomerProductInfo(cid IN Customers.CustomerId%TYPE, pid IN Products.ProductId%TYPE) as invalid_input EXCEPTION; order_date Orders.OrderDate%TYPE; check_cid Customers.CustomerId%TYPE; check_pid Products.ProductId%TYPE; CURSOR c_customer_product IS SELECT DISTINCT O.OrderDate FROM Orders O, Products P WHERE O.ProductId = pid AND O.CustomerId = cid; BEGIN OPEN c_customer_product; dbms_output.put_line('Records of customer id ' || cid || ' with product id ' || pid || ':'); SELECT CustomerId INTO check_cid FROM Customers WHERE CustomerId = cid; SELECT ProductId INTO check_pid FROM Products WHERE ProductId = pid; LOOP FETCH c_customer_product INTO order_date; EXIT WHEN c_customer_product%NOTFOUND; dbms_output.put_line('OrderDate: ' || order_date); END LOOP; CLOSE c_customer_product; EXCEPTION WHEN no_data_found THEN dbms_output.put_line('Invalid customer id or product id!'); WHEN others THEN dbms_output.put_line('Invalid customer id or product id!'); END CustomerProductInfo; / -- show error procedure CustomerProductInfo; BEGIN CustomerProductInfo(1,1); CustomerProductInfo(-1,1); CustomerProductInfo(1,-1); CustomerProductInfo(-1,-1); CustomerProductInfo(100,100); CustomerProductInfo(4,3); CustomerProductInfo(2,5); CustomerProductInfo(7,11); CustomerProductInfo(8,9); CustomerProductInfo(9,5); END; /