Data Warehouse Management Systems
Data Warehouse Management Systems
1 Design of 5% 1
Include the relevant dimensions.
Data
warehous
Excellent (5) Good (4) Moderate (2-3) Poor (0-1)
e Include the correct measures in the fact table.
(logical
design)
Design of 15% 1
Create TABLE statements
Data
warehous
e Appropriate data types and size ofExcellent
attributes(13-15) Good (10-12) Moderate (6-9) Poor (0-5)
(physical
design) Proper Integrity constraints
2 ETL 20% 1
(initial
loading)
Excellent (18-20) Good (14-17) Moderate (9-13) Poor (0-8)
VIEWS, SELECT,INSERT,PROCEDURES for each of the dimensions and fact table. Variety of techn
ETL 20% 1
(subsequ
ent
loading) VIEWS, SELECT,INSERT,PROCEDURES for each of the dimensions and fact table. Logic to scrub dirty data
Excellent (18-20) Good (15-17) Moderate (9-14) Poor (0-8)
3 *Business 30% 3
Analytic Clear and proper identification of information needs
queries
design Excellent (25-30) Good (16-24) Moderate (9-15) Poor (0-8)
(Individual
marks Flexible query to cater for variety of inputs, use of multiple tables
awarded))
Meaningful report handlings
4 Assignmen 10% 1
Comprehensive coverage
t
Report
Quality of report presented Excellent (9-10) Good (7-8) Moderate (4-6) Poor (0-3)
1
Chapter 1 Design of Data Warehouse
2
1.1.2 Star Schema Dimension and Fact Tables
3
1.2 Physical Design
4
(product_key number not null,
productCode varchar(15) not null,
productName varchar(70),
productLine varchar(50),
productScale varchar(10),
productVendor varchar(50),
buyPrice number(7,2),
MSRP number(7,2),
primary key(product_key)
);
5
primary key(date_key, product_key, customer_key,
office_key, employee_key,orderNumber)
);
6
employeeNumber NUMBER(11) NOT NULL Employee’s ID 1611, 1501
7
productName VARCHAR(70) - Product’s name Triumph
Spitfire, Buick
Runabout
8
Cal_Month_Na VARCHAR(9) - Month’s name Jan, Feb
me
9
priceEach NUMBER(7,2) - Price for each 102.05
product
select customer_key,
customerNumber, customerName, creditLimit
from DIM_customers;
10
2.1.2 Employees Dimension
drop sequence emp_seq;
create sequence emp_seq
start with 10001
increment by 1;
11
insert into DIM_office ....
end if
end loop
select officeCode, state
from offices;
12
Cal_Week_in_Year number(2),
Cal_Month_Name varchar(9),
Cal_Month_No_in_Year number(2),
Cal_Year_Month char(7),
Cal_Quarter char(2),
Cal_Year_Quarter char(6),
Cal_Year number(4),
Holiday_Ind char(1),
Weekday_Ind char(1),
PRIMARY KEY(date_key)
);
declare
every_date date;
end_date date;
v_day_of_week number(1);
v_day_of_month number(2);
v_day_of_year number(3);
last_day_month_ind char(1);
v_week_end_date date;
v_week_in_year number(2);
v_month_name varchar(9);
v_month_no number(2);
v_year_month char(7);
v_quarter char(2);
v_year_quarter char(6);
v_year number(4);
v_holiday_ind char(1);
v_weekday_ind char(1);
begin
every_date := to_date('01/01/2019','dd/mm/yyyy');
end_date := to_date('31/01/2022','dd/mm/yyyy');
v_holiday_ind :='N';
v_week_end_date := every_date+(7-
(to_char(every_date,'d')));
v_week_in_year := to_char(every_date,'IW');
v_month_name := to_char(every_date,'MONTH');
v_month_no := extract (month from every_date);
v_year_month := to_char(every_date,'YYYY-MM');
13
if (v_month_no<=3) then
v_quarter := 'Q1';
elsif (v_month_no<=6) then
v_quarter := 'Q2';
elsif (v_month_no<=9) then
v_quarter := 'Q3';
else
v_quarter := 'Q4';
end if;
14
lineTotal number(9,2),
orderNumber number(11),
orderLineNumber number(3),
PRIMARY KEY(date_key, product_key, customer_key,
office_key, employee_key,orderNumber)
);
if SQL%FOUND then
dbms_output.put_line('Input date: '|| IN_DATE||
' updated as Holiday');
else
dbms_output.put_line('No such date');
end if;
end;
15
/
exec Update_Hol_prc('01-JAN-2022')
This report allows the user to view the overall performance of the employees and know which employee
has better performance and which employee is lacking in performance in the company. It can also help
the company to figure out the mean sales figures of their employees.
For example, by referring to the report, we can see that the employee - Castillo with ‘1401’ employee
number has the greatest working performance as she has completed 119334 orders and gain around 65
million sales for the company
SQL Query
--Internal Report
--Employee Performance Report
set serveroutput on;
set linesize 200;
set pagesize 50;
CURSOR csr_orderperemployee IS
16
SELECT e.employeenumber, e.lastname, count(s.ordernumber),
sum(s.linetotal) as sales
FROM dim_employees e, sales_fact s
where e.employee_key = s.employee_key
group by e.employeenumber, e.lastname
order by sum(s.linetotal) desc;
BEGIN
DBMS_OUTPUT.PUT_LINE(LPAD ('=',85,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',58,' ')||
LPAD(' | ',26));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Internal Report',46,' ')||LPAD('
| ',38));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Employee Performance Report',52,'
') || ' ' || LPAD(' | ',31));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',81) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,71, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',85,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Employee Number',15)||' | '||
RPAD('Employee Name',15)||' | '||LPAD('Order Count',16)||' | '||
LPAD('Total Sales (RM)',26)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',85,'-'));
OPEN csr_orderperemployee;
LOOP
FETCH csr_orderperemployee INTO v_employeenumber,
v_employeename, v_ordercount, v_sales;
EXIT WHEN csr_orderperemployee%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_employeenumber,15)|| ' | '
|| RPAD(v_employeename,15)||' | ' ||
LPAD(to_char(v_ordercount,'999,999,999'),16)||' | '||
LPAD(to_char(v_sales,'999,999,999.99'),26)||' |');
END LOOP;
CLOSE csr_orderperemployee;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',85,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',46,' ') || ' ' ||
LPAD(' | ',37));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',85,'-'));
END;
/
exec prc_employeeperformancereport;
17
Results
The purpose of this report is to trace out the growth rate based on base year. It can see the growth rate
from 2016 to 2022. It can let the stakeholder to refer in order to make a better and clearer decision by
investing in the company.
For example, if we assume that the company starts up from 2016, then we will take it as the base year.
After 2016, in 2017, the company’s sales totaled 235k of orders and gained a profit of 59 million. Then,
the growth rate is calculated by using the profit divided by the base year(2016) each year and get the
company growth rate. So far as we can see, the sales of the company in 2016 is the best and it hasn’t been
surpassed yet even until 2021. 2022 is excluded from this report as it is an annual report and 2022 is not
over yet.
SQL Query
--Company Performance Growth Report
18
set serveroutput on;
set linesize 200;
set pagesize 50;
CURSOR csr_getalldata IS
select d.cal_year as year, count(s.ordernumber) as
countOfRecord, sum(s.linetotal) - sum(p.buyprice * s.quantityordered)
as profit,
--cal compare_base_year
coalesce(
(sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) /
(select (sum(s.linetotal) - sum(p.buyprice *
s.quantityordered))
from sales_fact s
join dim_products p on s.product_key = p.product_key
join dim_date d on s.date_key = d.date_key
where d.cal_year = '2016'),0) * 100 as
compare_base_year
from sales_fact s
join dim_date d on s.date_key = d.date_key
join dim_products p on s.product_key = p.product_key
where d.cal_year NOT LIKE '2022'
group by d.cal_year
order by d.cal_year;
BEGIN
OPEN csr_getalldata;
DBMS_OUTPUT.PUT_LINE(LPAD ('=',81,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',54,' ')||
LPAD(' | ',26));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Company Growth Report',48,' ') ||
' ' || LPAD(' | ',31));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',77) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,66, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',81,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Year',6)||' | '||LPAD('Number of
Orders',18)||' | '||LPAD('Profit (RM)',16)||' | '||
LPAD('Growth Rate to Base Year (%)',28)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',81,'-'));
19
LOOP
FETCH csr_getalldata INTO v_year, v_countrecord, v_profit,
v_baseyear;
EXIT WHEN csr_getalldata%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_year,6)|| ' | '||
LPAD(to_char(v_countrecord,'999,999,999'),18)|| ' | ' ||
LPAD(to_char(v_profit,'999,999,999.99'),16)
||' | '|| LPAD(to_char(v_baseyear,'999,999,990.99'),28)||'
|');
END LOOP;
CLOSE csr_getalldata;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',81,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',46,' ') || ' ' ||
LPAD(' | ',33));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',81,'-'));
END;
/
exec prc_growthreport;
Results
20
For example, after the sales report based on the country is printed, we can see that the top sales country is
Ireland. After that, if we want to know the TOP 10 products that get the highest sales in Ireland, the sales
manager and marketing manager can refer to this report. From this report, they can see that the most
popular product is the Alpine Renault 1300 which has the highest sales, which is around 266K and this
sales contribute 2.03% to the total sales of Ireland.
SQL Query
--Top Sales Country - Ireland TOP 10 Product Analysis Report
set serveroutput on;
set linesize 200;
set pagesize 50;
CURSOR csr_topten IS
SELECT product, sales, contribution
FROM productIrelandView
where rownum <= 10;
BEGIN
DBMS_OUTPUT.PUT_LINE(LPAD ('=',91,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',63,' ')||
LPAD(' | ',27));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Ireland TOP 10 Product Analysis
Report',64,' ') || ' ' || LPAD(' | ',25));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',87) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,77, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',91,'-'));
--for header
21
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Product',50)||' | '||LPAD('Sales
(RM)',15)||' | '||LPAD('Contribution (%)',16)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',91,'-'));
OPEN csr_topten;
LOOP
FETCH csr_topten INTO v_product, v_sales, v_contribution;
EXIT WHEN csr_topten%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_product,50)|| ' | ' ||
LPAD(to_char(v_sales,'999,999,999.99'),15)||' | '||
LPAD(v_contribution,16)||' |');
END LOOP;
CLOSE csr_topten;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',91,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',46,' ') || ' ' ||
LPAD(' | ',43));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',91,'-'));
END;
/
exec prc_irelandanalysis;
Results
22
3.2 Khoo Shi Zhao
This report is able to let the company visualize their improvements over the years so that they can
determine which business tactic is the best for maximum improvements year after year.
For example, by referring to the report, the readers can know that the sales of the company grow during
2017 compared to 2016. The profit ratio will help the reader to have a clearer understanding about the
grow of the company sales as it also represents the company sales trend. If the profit ratio is over 1.00,
that means that the profit is growing by 3%+, else, it will represents that the profit drops.
SQL Query
--Company Overall Performance Report with Trend
set serveroutput on;
set linesize 200;
set pagesize 50;
drop procedure prc_comperformance;
CURSOR csr_getall IS
select d.cal_year as year, sum(s.linetotal) - sum(p.buyprice *
s.quantityordered) as profit,
coalesce(LAG(sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) OVER ( ORDER BY d.cal_year ),0) AS
Profit_Previous_Year,--Lag is use to delay one row
--cal profit ratio based on previous year formula(profit
this year / profit previous year)
coalesce(round((sum(s.linetotal) - sum(p.buyprice *
s.quantityordered))/
(LAG(sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) OVER ( ORDER BY d.cal_year )),2) ,0) AS
profit_ratio
from sales_fact s
join dim_date d on s.date_key = d.date_key
23
join dim_products p on s.product_key = p.product_key
where d.cal_year NOT LIKE '2022'
group by d.cal_year
order by d.cal_year;
BEGIN
OPEN csr_getall;
DBMS_OUTPUT.PUT_LINE(LPAD ('=',78,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',52,' ')||
LPAD(' | ',25));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Company Overall Performance
Report (Yearly)',56,' ') || ' ' || LPAD(' | ',20));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',74) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,63, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',78,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Year',6)||' | '||LPAD('Profit
(RM)',15)||' | '||
LPAD('Profit of Previous Year (RM)',30)||' | '||LPAD('Profit
Ratio',14)||' | ');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',78,'-'));
LOOP
FETCH csr_getall INTO v_year, v_profit, v_profitpreyear,
v_profitratio;
EXIT WHEN csr_getall%NOTFOUND;
24
LPAD(to_char(v_profit,'999,999,999.99'),15)
||' | ' ||
LPAD(to_char(v_profitpreyear,'999,999,990.99'),30)||' | '||
LPAD(to_char(v_profitratio,'990.99'),14)||
' | ');
END LOOP;
CLOSE csr_getall;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',78,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',46,' ') || ' ' ||
LPAD(' | ',30));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',78,'-'));
END;
/
exec prc_comperformance;
Results
The purpose of this report is to compare the sales among the offices. It can create a competitive challenge
among the offices. So that, the employee in the office can contribute more effort in finding the sales to
increase the rank of the office.
For example, the office with the code 1 originates from USA has a total sales figure of 222 million+ and
25
a profit of 102 million+. The contribution beside indicates that the office contributed 27.88% to the
company’s overall revenue and is the best performing office branch of PSMS.
SQL Query
--Report Based on office (overall)
--office report
CURSOR csr_getofficereport IS
select officecode, country, sum(s.linetotal) as sales,
sum(s.linetotal) - sum(s.quantityordered * p.buyprice) as
profit,
(round((sum(s.quantityordered * p.buyprice)/(select
sum(s.quantityordered * p.buyprice) from sales_fact s, dim_products p
where s.product_key = p.product_key))*100,2)) as contribution
from dim_offices o
join sales_fact s on s.office_key = o.office_key
join dim_products p on s.product_key = p.product_key
group by officecode, country
order by sum(s.linetotal) - sum(s.quantityordered *
p.buyprice) desc;
BEGIN
OPEN csr_getofficereport;
DBMS_OUTPUT.PUT_LINE(LPAD('=',92,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',63,' ')||LPAD(' | ',28));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Overall Office Performance
Report',62,' ') || ' ' || LPAD(' | ',28));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',88) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,76, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',92,'-'));
26
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Office Code',13)||' | '||
RPAD('Country',11)||' | '||LPAD('Sales (RM)',18)||' | '||
LPAD('Profit (RM)',18)||' | '||LPAD('Contribution (%)',16)||' |
');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',92,'-'));
LOOP
FETCH csr_getofficereport INTO v_officecode, v_country,
v_sales, v_profit, v_contribution;
EXIT WHEN csr_getofficereport%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_officecode,13)|| ' | '||
RPAD(v_country,11)||' | '||
LPAD(to_char(v_sales,'999,999,999.99'),18)||
' | '|| LPAD(to_char(v_profit,'999,999,999.99'),18)||' | '||
LPAD(to_char(v_contribution,'999,999,999.99'),16)||' | ');
END LOOP;
CLOSE csr_getofficereport;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',92,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',55,' ')||LPAD(' |
',36));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',92,'-'));
END;
/
exec prc_officereport;
Results
27
3.2.3 Report Based on Product Category
The report generated based on the product category will consist of information about the product line, top
3 highest sales product and the total number of sales in said product line. It will also show the ranking of
the products so that we will know the top 3 products in their respective product lines.
The purpose of this report is to find out the top 3 rank of each category of the product which has the
highest sales. This is to trace out our favorite product that most of the customers prefer. It can do the
forecasting and make promotions to increase the sales based on this report.
For example, the top 3 products from the “Motorcycles' ' product line are the Harley Davidson Eagle,
ranked 1, Suzuki XREO, ranked 2, and the Moto Guzzi 1100i, ranked 3. The rankings are ranked based
on the sales of the product type. By referring to this report, we can know the popular product among
customers and the revenue from each type of product.
SQL Query
--Report Based on Product Category (overall)
set serveroutput on;
set linesize 200;
set pagesize 50;
28
CURSOR csr_getproductline IS
SELECT productline, product, sales, productrank from
typeSalesView
where productrank <= 3;
BEGIN
OPEN csr_getproductline;
DBMS_OUTPUT.PUT_LINE(LPAD('=',106,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',70,' ')||LPAD(' | ',35));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Report Based on Product
Category',69,' ') || ' ' || LPAD(' | ',35));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',102) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,90, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',106,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Product Line',17)||' | '||
RPAD('TOP 3 Highest Sales Product',40)||' | '||LPAD('Sales
(RM)',21)||' | '||LPAD('Rank',15)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',106,'-'));
LOOP
FETCH csr_getproductline INTO v_productline, v_product,
v_sales, v_custrank;
EXIT WHEN csr_getproductline%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_productline,17)|| ' | '||
RPAD(v_product,40)||' | '||
LPAD(to_char(v_sales,'999,999,999.99'),21)||
' | '||LPAD(v_custrank,15)||' | ');
END LOOP;
CLOSE csr_getproductline;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',106,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',60,' ') || ' ' ||
LPAD(' | ',44));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',106,'-'));
END;
/
exec prc_productlinesales;
29
Results
The purpose of this report is to let the offices see the total number of customers and the total quantity of
the product that was bought by the customer. It can see the employees of the offices make some effort to
attract the customers and increase the sales.
For example, the office branch situated at USA with the office code 1, 3, and 2 has a total sale of
RM222,121,173.99, RM98,739,650.51, and RM79,354,171.06 and have total number of customers of
4,352, 1,920, and 1,536 respectively. The total number of orders are 162,195, 72,266, and 57,733. The
three branches in the USA each contribute 27.76%, 12.34% and 9.92% respectively to the total profit of
the company.
SQL Query
Results
30
--office code, country, number of customer, qty order, average of qty
if each customer buy
-- add sales
set serveroutput on;
set linesize 200;
set pagesize 50;
CURSOR csr_getoffice IS
select o.officecode, o.country, sum(s.linetotal) as
total_sales, count(distinct s.customer_key) as number_Of_Customer,
count(distinct s.ordernumber) as number_Of_Order,
round(sum(s.linetotal)/(select sum(linetotal) from
sales_fact) * 100, 2) as Contribution
from dim_offices o
join sales_fact s on o.office_key = s.office_key
group by officecode, country
order by count(distinct s.customer_key) desc;
BEGIN
OPEN csr_getoffice;
DBMS_OUTPUT.PUT_LINE(LPAD ('=',108,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',72,' ')||
LPAD(' | ',35));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Office Branch Performance
Report',70,' ') || ' ' || LPAD(' | ',36));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',104) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,93, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',108,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Office Code',14)||' | '||
31
RPAD('Country',9)||' | '||LPAD('Sales (RM)',15)||' | '||LPAD('Total
Customer',16)||' | '||
LPAD('Number of Order',17)||' | '||LPAD('Contribution (%)',18)||'
|');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',108,'-'));
LOOP
FETCH csr_getoffice INTO v_officecode, v_country, v_sales,
v_custcount, v_ordercount, v_contribution;
EXIT WHEN csr_getoffice%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_officecode,14)|| ' | '||
RPAD(v_country,9)|| ' | ' ||
LPAD(to_char(v_sales,'999,999,999.99'),15)||' | '||
LPAD(to_char(v_custcount,'999,999,999'),16)||' | '
||LPAD(to_char(v_ordercount,'999,999,999'),17)||' | '||
LPAD(to_char(v_contribution,'999,999,990.99'),18)||' |');
END LOOP;
CLOSE csr_getoffice;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',108,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',60,' ') || ' ' ||
LPAD(' | ',46));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',108,'-'));
END;
/
exec prc_branchreport;
32
This report will find the potential customers and see the average of the sale of each of the customers
bought and the quantity of the customer ordered. It can let the user view the sales details of the potential
customers. Company can improve its sales analysis and response time to inquiries.
For example, the customer Oulu Toy Supplies from Finland placed an order of 70 units and resulted in a
total sale of RM50,635 and an average sale per order of RM723.35.
SQL Query
--customer average sales per order / customer report
set serveroutput on;
set linesize 200;
set pagesize 50;
BEGIN
DBMS_OUTPUT.PUT_LINE(LPAD ('=',109,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',73,' ')||
LPAD(' | ',35));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Customer Sales Details
Report',71,' ') || ' ' || LPAD(' | ',36));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',105) ||' | ');
33
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,95, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',109,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Customer Name',25)||' | '||
RPAD('Country',14)||' | '||LPAD('No. of Order',12)||' | '||LPAD('Sales
(RM)',13)||' |'||LPAD('Average Sales per Order (RM)',30)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',109,'-'));
OPEN csr_top20custlist;
LOOP
FETCH csr_top20custlist INTO v_customername, v_country,
v_ordercount, v_salestotal, v_averagesales;
EXIT WHEN csr_top20custlist%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_customername,26)||'| '||
RPAD(v_country,15)||'| '||RPAD(v_ordercount,13)||'| '||
RPAD(to_char(v_salestotal,'999,999,999'),13)|| ' | ' ||
LPAD(to_char(v_averagesales,'999,999,999.99'),29)||' |');
END LOOP;
CLOSE csr_top20custlist;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',109,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',59,' ') || ' ' ||
LPAD(' | ',48));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',109,'-'));
END;
/
exec prc_customerreport;
34
Results
The purpose of this report is to let the company know the expenses of the first 3 order from each of the
vendors. It can say that the higher the order purchased from the vendor, the higher the sales made by the
company.
For example, the highest 3 rank vendor's product in Autocart Studio Design is Ford Mustag that the sales
is RM14247193.68 followed by BMW R 1100 S, sales is RM8258656.00 and the third model is Model A
Ford J-Courpe, sales is RM9238664.23.
SQL Query
--Report Based on Vendors (overall)
set serveroutput on;
set linesize 200;
set pagesize 50;
35
select productvendor as vendor,
concat(p.productcode,p.productname) as product, p.buyprice,
sum(s.linetotal) as totalsales, count(s.ordernumber) as orderquantity,
RANK() over(PARTITION BY productvendor order by
count(s.ordernumber) desc) as productrank
from sales_fact s
join dim_products p on p.product_key = s.product_key
group by productvendor, concat(p.productcode,p.productname),
p.buyprice;
CURSOR csr_getvendortop3 IS
SELECT vendor, product, buyprice, totalsales, orderquantity,
productrank
FROM allvendorsView
where productrank <= 3;
BEGIN
OPEN csr_getvendortop3;
DBMS_OUTPUT.PUT_LINE(LPAD('=',140,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',84,' ')||LPAD(' | ',55));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Overall Vendor Analytic
Report',81,' ') || ' ' || LPAD(' | ',57));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',136) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,123, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',140,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Vendor Name',25)||' | '||
RPAD('Product Name',45)||' | '||LPAD('Buy Price (RM)',16)||
' | '||LPAD('No. of Order',12)||' | '||LPAD('Sales (RM)',17)||' |
'||LPAD('Rank',6)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',140,'-'));
LOOP
FETCH csr_getvendortop3 INTO v_vendor, v_product, v_buyprice,
36
v_totalsales, v_orderquantity, v_productrank;
EXIT WHEN csr_getvendortop3%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_vendor,25)|| ' | '||
RPAD(v_product,45)||' | '||
LPAD(to_char(v_buyprice,'999,999,999.99'),16)||
' | '||LPAD(v_orderquantity,12)||' | '||
LPAD(to_char(v_totalsales,'999,999,999.99'),17)||
' | '||LPAD(v_productrank,6)||' | ');
END LOOP;
CLOSE csr_getvendortop3;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',140,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',78,' ') || ' ' ||
LPAD(' | ',60));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',140,'-'));
END;
/
exec prc_vendorreport;
Results
37
3.4 Keoh Ji Xiang
The purpose of this report being generated is to allow the users to have an overall view of the company’s
performance in 2021 combined into one report instead of needing them to view multiple reports to get the
same information.
For example, the product 1952 Alpine Renault 1300 was the number one product in 2021 and it costs the
company a total expense of RM1,103,110.20 in 2021 and achieve a total sale of RM2,398,017.00
resulting in a profit of RM1,121,695.92 and a sale contribution percentage of 2.25%.
SQL Query
Results
--ANNUAL REPORT OF 2021
set serveroutput on;
set linesize 200;
set pagesize 50;
38
v_sales number(13,2);
v_profit number(13,2);
v_contribution number(4,2);
v_sumexpenses number(13,2);
v_sumsales number(13,2);
v_sumprofit number(13,2);
CURSOR csr_getdata IS
select * from(
select productcode, productname, sum(p.buyprice *
s.quantityordered) as expenses,
sum(s.linetotal) as sales, sum(s.linetotal) -
sum(p.buyprice * s.quantityordered) as profit,
ROUND((sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) /
(select sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)
from sales_fact s join dim_products p on s.product_key
= p.product_key)*100,2) as contribution
from sales_fact s
join dim_date d on s.date_key = d.date_key
join dim_products p on s.product_key = p.product_key
where d.cal_year = '2021'
group by productcode, productname
order by (sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) /
(select sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)
from sales_fact s join dim_products p on s.product_key
= p.product_key) desc)
where rownum <=10;
CURSOR csr_gettotal IS
select sum(expenses), sum(sales), sum(profit) from(
select productcode, productname, sum(p.buyprice *
s.quantityordered) as expenses,
sum(s.linetotal) as sales, sum(s.linetotal) -
sum(p.buyprice * s.quantityordered) as profit,
ROUND((sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) /
(select sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)
39
from sales_fact s join dim_products p on s.product_key
= p.product_key)*100,2) as contribution
from sales_fact s
join dim_date d on s.date_key = d.date_key
join dim_products p on s.product_key = p.product_key
where d.cal_year = '2021'
group by productcode, productname
order by (sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) /
(select sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)
from sales_fact s join dim_products p on s.product_key
= p.product_key) desc)
where rownum <=10;
BEGIN
--OPEN csr_getdata(v_reportyear);
OPEN csr_getdata;
DBMS_OUTPUT.PUT_LINE(LPAD ('=',129,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',82,' ')||
LPAD(' | ',46));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Annual Report for the Year of
2021',82,' ') || ' ' || LPAD(' | ',45));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',124) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,113, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',129,'-'));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',129,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Product Code',12)||' | '||
RPAD('Product Name',25)||' | '||LPAD('Expenses (RM)',16)||' | '||
LPAD('Sales (RM)',16)||' | '||
LPAD('Profit (RM)',16)||' | '||LPAD('Profit Contribution
(%)',25)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',129,'-'));
LOOP
FETCH csr_getdata INTO v_productcode, v_productname,
v_expenses, v_sales, v_profit, v_contribution;
EXIT WHEN csr_getdata%NOTFOUND;
40
DBMS_OUTPUT.put_line('| '||RPAD(v_productcode,12)|| ' | '||
RPAD(v_productname,25)|| ' | ' ||
LPAD(to_char(v_expenses,'999,999,999.99'),16)
||' | ' || LPAD(to_char(v_sales,'999,999,999.99'),16)||' | '||
LPAD(to_char(v_profit,'999,999,999.99'),16)||
' | '||LPAD(to_char(v_contribution,'990.99'),25)||' | ');
END LOOP;
CLOSE csr_getdata;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',129,'-'));
OPEN csr_gettotal;
FETCH csr_gettotal INTO v_sumexpenses, v_sumsales, v_sumprofit;
--display total
DBMS_OUTPUT.PUT_LINE(LPAD ('*',129,'*'));
DBMS_OUTPUT.PUT_LINE('| ' || LPAD('Total Expenses in the Year of
2021 (RM): ',109,' ')|| to_char(v_sumexpenses,'999,999,999.99')
|| ' | ');
DBMS_OUTPUT.PUT_LINE('| ' || LPAD('Total Sales in the Year of 2021
(RM): ',109,' ')|| to_char(v_sumsales,'999,999,999.99')
|| ' | ');
DBMS_OUTPUT.PUT_LINE('| ' || LPAD('Total Profit in the Year of
2021 (RM): ',109,' ')|| to_char(v_sumprofit,'999,999,999.99')
|| ' | ');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',129,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',70,' ') || ' ' ||
LPAD(' | ',57));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',129,'-'));
CLOSE csr_gettotal;
END;
/
41
3.4.2 Monthly Performance Report
The monthly report will contain information such as the profit obtained each month, and the profit of the
previous month so that the profit ratio can be calculated and be displayed in percentage. Finally it will
also show the total order count from each month
The purpose of this report is to show the user a more detailed monthly report as compared to the annual
report. The report breaks down the annual sales into months for a more detailed look at the company
sales.
For example, the sales in February had a total profit of RM27,460,660.81. And the profit in the previous
month, January, had a total profit of RM36,020,464.38 resulting in a profit ratio of 76% which was a 24%
decline. February has a total order count of 108065 while the total order in January is 141501.
SQL Query
--Monthly Performance for the year of 2021
set serveroutput on;
set linesize 200;
set pagesize 50;
CURSOR csr_getmonthly IS
42
select d.cal_month_no_in_year as month, sum(s.linetotal) -
sum(p.buyprice * s.quantityordered) as profit,
coalesce(LAG(sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) OVER ( ORDER BY d.cal_month_no_in_year ),0) AS
Profit_Previous_Month,--Lag is use to delay one row
--cal profit ratio based on previous year formula(profit
this year / profit previous year)
coalesce((round((sum(s.linetotal) - sum(p.buyprice *
s.quantityordered))/
(LAG(sum(s.linetotal) - sum(p.buyprice *
s.quantityordered)) OVER ( ORDER BY d.cal_month_no_in_year )),2)),0)
AS profit_ratio,
--cal count of record for the particular year
count(s.ordernumber) as countOfRecord
from sales_fact s
join dim_date d on s.date_key = d.date_key
join dim_products p on s.product_key = p.product_key
group by d.cal_month_no_in_year
order by d.cal_month_no_in_year;
BEGIN
OPEN csr_getmonthly;
DBMS_OUTPUT.PUT_LINE(LPAD ('=',103,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',70,' ')||
LPAD(' | ',32));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Monthly Performance for the Year
of 2021',73,' ') || ' ' || LPAD(' | ',28));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',99) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,89, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',103,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Month',12)||' | '||LPAD('Profit
(RM)',16)||' | '||LPAD('Profit of Previous Month (RM)',31)||' | '||
LPAD('Profit Ratio',14)||' | '||LPAD('No. of Order',14)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',103,'-'));
LOOP
FETCH csr_getmonthly INTO v_month, v_profit, v_profitprev,
v_profitratio, v_count;
EXIT WHEN csr_getmonthly%NOTFOUND;
IF v_month = 1 THEN
43
v_month2 := 'January';
ELSIF v_month = 2 THEN
v_month2 := 'February';
ELSIF v_month = 3 THEN
v_month2 := 'March';
ELSIF v_month = 4 THEN
v_month2 := 'April';
ELSIF v_month = 5 THEN
v_month2 := 'May';
ELSIF v_month = 6 THEN
v_month2 := 'June';
ELSIF v_month = 7 THEN
v_month2 := 'July';
ELSIF v_month = 8 THEN
v_month2 := 'August';
ELSIF v_month = 9 THEN
v_month2 := 'September';
ELSIF v_month = 10 THEN
v_month2 := 'October';
ELSIF v_month = 11 THEN
v_month2 := 'November';
ELSIF v_month = 12 THEN
v_month2 := 'December';
END IF;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',103,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',58,' ') || ' ' ||
LPAD(' | ',43));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',103,'-'));
END;
/
exec prc_monthlyreport;
Results
44
3.4.3 Customer Country Analysis
The customer country analysis report will contain the information regarding where PSMS’s customers are
from and the top 3 highest sale customers. It will display the top 3 customer sales in each of the country
PSMS’s customers are from. The report will also show the amount of each sale and the ranking of the sale
in that specific country.
Based on the report, it can help the user to focus the sales on a certain country. For example, the user can
maintain the customer which has higher potential to avoid customer churn. So, by fulfilling the
customers’ request, users can refer to this report to make better decisions and plan better strategies to
attract more customers based on their requirement.
For example, in Australia, Australian Coll07187 has the highest sales which is RM88,844 and followed
by Souvenirs And 114,332 and 105,426 which is RM87,035 and RM81955.
45
SQL Query
--Analysis Based on Customer Country
set serveroutput on;
set linesize 200;
set pagesize 50;
BEGIN
DBMS_OUTPUT.PUT_LINE(LPAD ('=',80,'='));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Popular Scale Model Supplier
(PSMS)',55,' ')||
LPAD(' | ',24));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('Analysis Based on Customer
Country',55,' ') || ' ' || LPAD(' | ',23));
DBMS_OUTPUT.PUT_LINE('| '|| RPAD(' ',76) ||' | ');
DBMS_OUTPUT.PUT_LINE('| '|| LPAD('Report Generated:' ,66, ' ')||
TO_DATE(SYSDATE, 'DD-MON-YYYYHH24:MI:SS') || ' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',80,'-'));
--for header
DBMS_OUTPUT.PUT_LINE('| '||RPAD('Country',16)||' | '||RPAD('TOP 3
Highest Sale Customer',30)||' | '||LPAD('Sales (RM)',15)||' | '||
LPAD('Rank',6)||' |');
DBMS_OUTPUT.PUT_LINE(LPAD ('-',80,'-'));
46
OPEN csr_getsalesbycountry;
LOOP
FETCH csr_getsalesbycountry INTO v_country, v_customername,
v_linetotal, v_customerrank;
EXIT WHEN csr_getsalesbycountry%NOTFOUND;
DBMS_OUTPUT.put_line('| '||RPAD(v_country,16)|| ' | ' ||
RPAD(v_customername,30)||' | ' ||
LPAD(to_char(v_linetotal,'999,999,999'),15)||' | '||
LPAD(v_customerrank,6)||' |');
END LOOP;
CLOSE csr_getsalesbycountry;
DBMS_OUTPUT.PUT_LINE(LPAD ('-',80,'-'));
DBMS_OUTPUT.PUT_LINE('| '||LPAD('End Of Report',45,' ') || ' ' ||
LPAD(' | ',33));
DBMS_OUTPUT.PUT_LINE(LPAD ('-',80,'-'));
END;
/
exec prc_analysiscustomercountry;
47
Results
48
49
50