HARD

Getting Started
How can I access the schemas, tables, and data used in the practice problems? Use livesql.oracle.com. All schemas and tables utilized in the current practice problem sets are readily available without the headache of software installation. Simply create an account and let the SQL mastering begin! For a subset of the problems, a script is required to be executed to create and subsequently populate the table referenced within the problem. Simply copy and paste the corresponding script provided in the Tables Requiring Script Execution section of the SQL PRACTICE PROBLEMS page.

Schema and Table Information
Information on the schemas, corresponding tables, and data used in the example problems can be found within the SQL PRACTICE PROBLEMS page. I recommend opening another browser window with this page pulled up for quick reference.

Problem 1
Associate Turn-over
The human resource department is concerned that recent associate turn-over is largely attributed to dissatisfaction with salary. The first step HR wishes to take is to raise all employee salaries that are less than the midpoint of the salary range corresponding to the employee’s job. They’ve asked you to generate a report that contains only those employees meeting this condition. The necessary context required for the report is the employee ID, employee first name, employee last name, hire date, job title, current salary, minimum salary for the job, maximum salary for the job, and the new salary. The new salary should be the salary required to bring the employee’s salary to the midpoint value for the job. In addition, HR has asked, if possible, include the percent increase based on the old salary and new salary for each employee meeting the conditions of the report. Sort the report by percent increase, descending.

Table(s) Required

hr.employees
hr.jobs

Expected Output
EMPLOYEE_IDFIRST_NAMELAST_NAMEHIRE_DATEJOB_TITLESALARYMIN_SALARYMAX_SALARYNEW_SALARYPERCENT_INCREASE
132TJOlson10-Apr-07Stock Clerk210020085000350466.85714286
107DianaLorentz7-Feb-07Programmer4200400010000700066.66666667
191RandallPerkins19-Dec-07Shipping Clerk250025005500400060
182MarthaSullivan21-Jun-07Shipping Clerk250025005500400060
119KarenColmenares10-Aug-07Purchasing Clerk250025005500400060
128StevenMarkle8-Mar-08Stock Clerk220020085000350459.27272727
136HazelPhiltanker6-Feb-08Stock Clerk220020085000350459.27272727
198DonaldOConnell21-Jun-07Shipping Clerk260025005500400053.84615385
199DouglasGrant13-Jan-08Shipping Clerk260025005500400053.84615385
118GuyHimuro15-Nov-06Purchasing Clerk260025005500400053.84615385
173SunditaKumar21-Apr-08Sales Representative6100600012008900447.60655738
135KiGee12-Dec-07Stock Clerk240020085000350446
127JamesLandry14-Jan-07Stock Clerk240020085000350446
106ValliPataballa5-Feb-06Programmer4800400010000700045.83333333
105DavidAustin25-Jun-05Programmer4800400010000700045.83333333
167AmitBanda21-Apr-08Sales Representative6200600012008900445.22580645
179CharlesJohnson4-Jan-08Sales Representative6200600012008900445.22580645
149EleniZlotkey29-Jan-08Sales Manager1050010000200801504043.23809524
117SigalTobias24-Jul-05Purchasing Clerk280025005500400042.85714286
183GirardGeoni3-Feb-08Shipping Clerk280025005500400042.85714286
195VanceJones17-Mar-07Shipping Clerk280025005500400042.85714286
166SundarAnde24-Mar-08Sales Representative6400600012008900440.6875
140JoshuaPatel6-Apr-06Stock Clerk250020085000350440.16
144PeterVargas9-Jul-06Stock Clerk250020085000350440.16
131JamesMarlow16-Feb-05Stock Clerk250020085000350440.16
116ShelliBaida24-Dec-05Purchasing Clerk290025005500400037.93103448
190TimothyGates11-Jul-06Shipping Clerk290025005500400037.93103448
148GeraldCambrault15-Oct-07Sales Manager1100010000200801504036.72727273
143RandallMatos15-Mar-06Stock Clerk260020085000350434.76923077
197KevinFeeney23-May-06Shipping Clerk300025005500400033.33333333
187AnthonyCabrio7-Feb-07Shipping Clerk300025005500400033.33333333
165DavidLee23-Feb-08Sales Representative6800600012008900432.41176471
101NeenaKochhar21-Sep-05Administration Vice President1700015000300002250032.35294118
102LexDe Haan13-Jan-01Administration Vice President1700015000300002250032.35294118
139JohnSeo12-Feb-06Stock Clerk270020085000350429.77777778
126IreneMikkilineni28-Sep-06Stock Clerk270020085000350429.77777778
196AlanaWalsh24-Apr-06Shipping Clerk310025005500400029.03225806
181JeanFleaur23-Feb-06Shipping Clerk310025005500400029.03225806
115AlexanderKhoo18-May-03Purchasing Clerk310025005500400029.03225806
161SarathSewall3-Nov-06Sales Representative7000600012008900428.62857143
178KimberelyGrant24-May-07Sales Representative7000600012008900428.62857143
155OliverTuvault23-Nov-07Sales Representative7000600012008900428.62857143
147AlbertoErrazuriz10-Mar-05Sales Manager1200010000200801504025.33333333
100StevenKing17-Jun-03President2400020080400003004025.16666667
130MozheAtkinson30-Oct-05Stock Clerk280020085000350425.14285714
164MatteaMarvins24-Jan-08Sales Representative7200600012008900425.05555556
180WinstonTaylor24-Jan-06Shipping Clerk320025005500400025
194SamuelMcCain1-Jul-06Shipping Clerk320025005500400025
172ElizabethBates24-Mar-07Sales Representative7300600012008900423.34246575
171WilliamSmith23-Feb-07Sales Representative7400600012008900421.67567568
134MichaelRogers26-Aug-06Stock Clerk290020085000350420.82758621
124KevinMourgos16-Nov-07Stock Manager580055008500700020.68965517
154NanetteCambrault9-Dec-06Sales Representative7500600012008900420.05333333
160LouiseDoran15-Dec-05Sales Representative7500600012008900420.05333333
186JuliaDellinger24-Jun-06Shipping Clerk340025005500400017.64705882
104BruceErnst21-May-07Programmer6000400010000700016.66666667
142CurtisDavies29-Jan-05Stock Clerk310020085000350413.03225806
159LindseySmith10-Mar-05Sales Representative8000600012008900412.55
153ChristopherOlsen30-Mar-06Sales Representative8000600012008900412.55
146KarenPartners5-Jan-05Sales Manager1350010000200801504011.40740741
189JenniferDilly13-Aug-05Shipping Clerk360025005500400011.11111111
138StephenStiles26-Oct-05Stock Clerk32002008500035049.5
125JuliaNayer16-Jul-05Stock Clerk32002008500035049.5
202PatFay17-Aug-05Marketing Representative60004000900065008.333333333
123ShantaVollman10-Oct-05Stock Manager65005500850070007.692307692
145JohnRussell1-Oct-04Sales Manager140001000020080150407.428571429
177JackLivingston23-Apr-06Sales Representative840060001200890047.19047619
129LauraBissot20-Aug-05Stock Clerk33002008500035046.181818182
133JasonMallin14-Jun-04Stock Clerk33002008500035046.181818182
188KellyChung14-Jun-05Shipping Clerk38002500550040005.263157895
176JonathonTaylor24-Mar-06Sales Representative860060001200890044.697674419
114DenRaphaely7-Dec-02Purchasing Manager11000800015000115004.545454545
193BritneyEverett3-Mar-05Shipping Clerk39002500550040002.564102564
175AlyssaHutton19-Mar-05Sales Representative880060001200890042.318181818
200JenniferWhalen17-Sep-03Administration Assistant44003000600045002.272727273
108NancyGreenberg17-Aug-02Finance Manager12008820016000121000.766155896
205ShelleyHiggins7-Jun-02Accounting Manager12008820016000121000.766155896
141TrennaRajs17-Oct-03Stock Clerk35002008500035040.114285714
158AllanMcEwen1-Aug-04Sales Representative900060001200890040.044444444
152PeterHall20-Aug-05Sales Representative900060001200890040.044444444
Solution
SELECT
    hr.employees.employee_id,
    hr.employees.first_name,
    hr.employees.last_name,
    hr.employees.hire_date,
    hr.jobs.job_title,
    hr.employees.salary,
    hr.jobs.min_salary,
    hr.jobs.max_salary,
    ((hr.jobs.min_salary + hr.jobs.max_salary) / 2) AS new_salary,
	(((((hr.jobs.min_salary + hr.jobs.max_salary) / 2)
		- hr.employees.salary)
        / hr.employees.salary)
        * 100
    ) AS percent_increase
FROM
    hr.employees
    INNER JOIN
    hr.jobs
        ON hr.employees.job_id = hr.jobs.job_id
        AND hr.employees.salary < ((hr.jobs.min_salary + hr.jobs.max_salary) / 2)
ORDER BY
    percent_increase DESC;
Video Explanation

Problem 2
Mentor-mentee Assignments
The organization has decided to start a mentorship program next month. This program is spearheaded by John Wayne. In order to kick-off the mentorship program, John needs a list of mentors and mentees. He’s decided that for the first iteration of the mentorship program, mentors will be the most senior employee, by hire date, for each job and mentees will be the most recently hired employee for each job. Mentees will be assigned a mentor with the same job and mentor-mentee assignments will be made only for those jobs with at least two employees. *Only one mentor-mentee assignment per job is necessary for this iteration of the mentorship program. John has requested that you generate a report containing the mentors and mentees based on his criteria. Include the mentor’s employee ID, mentor’s job ID, mentor’s hire date, mentee’s employee ID, mentee’s job ID, and mentee’s hire date in the report for additional context. Ensure the report is sorted by job ID, ascending.

*In the instances of multiple mentors, mentees, or both, having been hired on the same date and for the same job, the solution does not need to produce deterministic results.

Table(s) Required

hr.employees

Expected Output
MENTOR_IDMENTOR_JOB_IDMENTOR_HIRE_DATEMENTEE_IDMENTEE_JOB_IDMENTEE_HIRE_DATE
102AD_VP13-JAN-01101AD_VP21-SEP-05
109FI_ACCOUNT16-AUG-02113FI_ACCOUNT07-DEC-07
105IT_PROG25-JUN-05104IT_PROG21-MAY-07
115PU_CLERK18-MAY-03119PU_CLERK10-AUG-07
145SA_MAN01-OCT-04149SA_MAN29-JAN-08
156SA_REP30-JAN-04167SA_REP21-APR-08
184SH_CLERK27-JAN-04183SH_CLERK03-FEB-08
137ST_CLERK14-JUL-03128ST_CLERK08-MAR-08
122ST_MAN01-MAY-03124ST_MAN16-NOV-07
Solution
WITH mentor AS (
    SELECT
        hr.employees.employee_id,
        hr.employees.job_id,
        hr.employees.hire_date,
        ROW_NUMBER() OVER (
            PARTITION BY hr.employees.job_id
            ORDER BY hr.employees.hire_date
        ) AS hire_date_sequence_asc
    FROM
        hr.employees
),
mentee AS (
    SELECT
        hr.employees.employee_id,
        hr.employees.job_id,
        hr.employees.hire_date,
        ROW_NUMBER() OVER (
            PARTITION BY hr.employees.job_id
            ORDER BY hr.employees.hire_date DESC
        ) AS hire_date_sequence_desc
    FROM
        hr.employees
)
SELECT
    mentor.employee_id AS mentor_id,
    mentor.job_id AS mentor_job_id,
    mentor.hire_date AS mentor_hire_date,
    mentee.employee_id AS mentee_id,
    mentee.job_id AS mentee_job_id,
    mentee.hire_date AS mentee_hire_date
FROM
    mentor
    INNER JOIN
    mentee
        ON mentor.job_id = mentee.job_id
    	AND mentor.employee_id != mentee.employee_id
        AND mentor.hire_date_sequence_asc = 1
        AND mentee.hire_date_sequence_desc = 1
ORDER BY
    mentor.job_id;
 
-- Solution 2
SELECT
    mentor.employee_id AS mentor_id,
    mentor.job_id AS mentor_job_id,
    mentor.hire_date AS mentor_hire_date,
    mentee.employee_id AS mentee_id,
    mentee.job_id AS mentee_job_id,
    mentee.hire_date AS mentee_hire_date
FROM (
    SELECT
        hr.employees.employee_id,
        hr.employees.job_id,
        hr.employees.hire_date,
        ROW_NUMBER() OVER (
            PARTITION BY hr.employees.job_id
            ORDER BY hr.employees.hire_date
        ) AS hire_date_sequence_asc
    FROM
        hr.employees
    ) mentor
    INNER JOIN (
    SELECT
        hr.employees.employee_id,
        hr.employees.job_id,
        hr.employees.hire_date,
        ROW_NUMBER() OVER (
            PARTITION BY hr.employees.job_id
            ORDER BY hr.employees.hire_date DESC
        ) AS hire_date_sequence_desc
    FROM
        hr.employees
    ) mentee
        ON mentor.job_id = mentee.job_id
    	AND mentor.employee_id != mentee.employee_id
        AND mentor.hire_date_sequence_asc = 1
        AND mentee.hire_date_sequence_desc = 1
ORDER BY
    mentor.job_id;
Video Explanation

Problem 3
Fact-checking HR
The human resource department has recently made a claim that pay within each job is based strictly on the duration employed. Today, you’ve been tasked with investigating the claim by creating a report with the necessary data to conclude the claim can be supported or disproved. Is this claim substantiated by the employee data? Assume that every employee has been in the same position since being hired. In your report, only include details related to those jobs held by at least two employees. Sort the result set by job ID (ascending) and employment duration (descending). The method for determining whether the claim can be supported is up to you.

Table(s) Required

hr.employees
hr.jobs

Expected Output
EMPLOYEE_IDEMPLOYEE_NAMEJOB_TITLEHIRE_DATEEMPLOYMENT_DURATIONSALARYINCONSISTENCY_FLAGSALARY_SEQUENCE_DESC
102De Haan, LexAdministration Vice President13-JAN-0123.481700011
101Kochhar, NeenaAdministration Vice President21-SEP-0518.791700011
109Faviet, DanielAccountant16-AUG-0221.89900011
110Chen, JohnAccountant28-SEP-0518.77820012
111Sciarra, IsmaelAccountant30-SEP-0518.77770004
112Urman, Jose ManuelAccountant07-MAR-0618.33780013
113Popp, LuisAccountant07-DEC-0716.58690015
105Austin, DavidProgrammer25-JUN-0519.03480003
103Hunold, AlexanderProgrammer03-JAN-0618.51900011
106Pataballa, ValliProgrammer05-FEB-0618.42480013
107Lorentz, DianaProgrammer07-FEB-0717.41420004
104Ernst, BruceProgrammer21-MAY-0717.13600012
115Khoo, AlexanderPurchasing Clerk18-MAY-0321.13310011
117Tobias, SigalPurchasing Clerk24-JUL-0518.95280003
116Baida, ShelliPurchasing Clerk24-DEC-0518.53290012
118Himuro, GuyPurchasing Clerk15-NOV-0617.64260014
119Colmenares, KarenPurchasing Clerk10-AUG-0716.91250015
145Russell, JohnSales Manager01-OCT-0419.761400011
146Partners, KarenSales Manager05-JAN-0519.51350012
147Errazuriz, AlbertoSales Manager10-MAR-0519.321200013
148Cambrault, GeraldSales Manager15-OCT-0716.731100014
149Zlotkey, EleniSales Manager29-JAN-0816.441050015
156King, JanetteSales Representative30-JAN-0420.441000014
157Sully, PatrickSales Representative04-MAR-0420.34950006
174Abel, EllenSales Representative11-MAY-0420.151100012
158McEwen, AllanSales Representative01-AUG-0419.93900007
150Tucker, PeterSales Representative30-JAN-0519.441000014
159Smith, LindseySales Representative10-MAR-0519.328000011
168Ozer, LisaSales Representative11-MAR-0519.321150011
175Hutton, AlyssaSales Representative19-MAR-0519.3880008
151Bernstein, DavidSales Representative24-MAR-0519.28950016
152Hall, PeterSales Representative20-AUG-0518.88900007
162Vishney, ClaraSales Representative11-NOV-0518.651050013
160Doran, LouiseSales Representative15-DEC-0518.567500012
170Fox, TaylerSales Representative24-JAN-0618.45960005
169Bloom, HarrisonSales Representative23-MAR-0618.291000014
176Taylor, JonathonSales Representative24-MAR-0618.28860019
153Olsen, ChristopherSales Representative30-MAR-0618.278000011
177Livingston, JackSales Representative23-APR-0618.28400110
161Sewall, SarathSales Representative03-NOV-0617.677000015
154Cambrault, NanetteSales Representative09-DEC-0617.577500012
171Smith, WilliamSales Representative23-FEB-0717.378000011
163Greene, DanielleSales Representative19-MAR-0717.3950016
172Bates, ElizabethSales Representative24-MAR-0717.287300113
178Grant, KimberelySales Representative24-MAY-0717.127000115
155Tuvault, OliverSales Representative23-NOV-0716.627000115
179Johnson, CharlesSales Representative04-JAN-0816.516200018
164Marvins, MatteaSales Representative24-JAN-0816.457200114
165Lee, DavidSales Representative23-FEB-0816.376800116
166Ande, SundarSales Representative24-MAR-0816.286400117
167Banda, AmitSales Representative21-APR-0816.216200118
173Kumar, SunditaSales Representative21-APR-0816.216100119
184Sarchand, NanditaShipping Clerk27-JAN-0420.44420011
192Bell, SarahShipping Clerk04-FEB-0420.42400003
185Bull, AlexisShipping Clerk20-FEB-0519.38410012
193Everett, BritneyShipping Clerk03-MAR-0519.34390014
188Chung, KellyShipping Clerk14-JUN-0519.06380015
189Dilly, JenniferShipping Clerk13-AUG-0518.9360016
180Taylor, WinstonShipping Clerk24-JAN-0618.45320018
181Fleaur, JeanShipping Clerk23-FEB-0618.37310019
196Walsh, AlanaShipping Clerk24-APR-0618.2310019
197Feeney, KevinShipping Clerk23-MAY-0618.123000010
186Dellinger, JuliaShipping Clerk24-JUN-0618.03340017
194McCain, SamuelShipping Clerk01-JUL-0618.01320018
190Gates, TimothyShipping Clerk11-JUL-0617.992900011
187Cabrio, AnthonyShipping Clerk07-FEB-0717.413000110
195Jones, VanceShipping Clerk17-MAR-0717.32800112
198OConnell, DonaldShipping Clerk21-JUN-0717.042600113
182Sullivan, MarthaShipping Clerk21-JUN-0717.042500114
191Perkins, RandallShipping Clerk19-DEC-0716.552500014
199Grant, DouglasShipping Clerk13-JAN-0816.482600013
183Geoni, GirardShipping Clerk03-FEB-0816.422800112
137Ladwig, RenskeStock Clerk14-JUL-0320.98360011
141Rajs, TrennaStock Clerk17-OCT-0320.72350012
133Mallin, JasonStock Clerk14-JUN-0420.06330013
142Davies, CurtisStock Clerk29-JAN-0519.44310015
131Marlow, JamesStock Clerk16-FEB-0519.392500010
125Nayer, JuliaStock Clerk16-JUL-0518.97320004
129Bissot, LauraStock Clerk20-AUG-0518.88330013
138Stiles, StephenStock Clerk26-OCT-0518.7320014
130Atkinson, MozheStock Clerk30-OCT-0518.69280017
139Seo, JohnStock Clerk12-FEB-0618.4270018
143Matos, RandallStock Clerk15-MAR-0618.31260019
140Patel, JoshuaStock Clerk06-APR-0618.252500110
144Vargas, PeterStock Clerk09-JUL-0617.992500010
134Rogers, MichaelStock Clerk26-AUG-0617.86290016
126Mikkilineni, IreneStock Clerk28-SEP-0617.77270018
127Landry, JamesStock Clerk14-JAN-0717.482400111
132Olson, TJStock Clerk10-APR-0717.242100013
135Gee, KiStock Clerk12-DEC-0716.572400111
136Philtanker, HazelStock Clerk06-FEB-0816.422200112
128Markle, StevenStock Clerk08-MAR-0816.332200112
122Kaufling, PayamStock Manager01-MAY-0321.18790003
120Weiss, MatthewStock Manager18-JUL-0419.97800002
121Fripp, AdamStock Manager10-APR-0519.24820011
123Vollman, ShantaStock Manager10-OCT-0518.74650014
124Mourgos, KevinStock Manager16-NOV-0716.64580015
Solution
WITH applicable_job AS (
	SELECT
		hr.employees.job_id,
    	hr.jobs.job_title
	FROM
		hr.employees
		INNER JOIN
		hr.jobs
			ON hr.employees.job_id = hr.jobs.job_id
	GROUP BY
		hr.employees.job_id,
    	hr.jobs.job_title
	HAVING
		COUNT(hr.employees.employee_id) > 1
)
SELECT
	hr.employees.employee_id,
	hr.employees.last_name || ', ' || hr.employees.first_name AS employee_name,
	applicable_job.job_title,
	hr.employees.hire_date,	
	ROUND(MONTHS_BETWEEN(SYSDATE, hr.employees.hire_date) / 12, 2) AS employment_duration,
	hr.employees.salary,
	CASE
		WHEN LEAD(hr.employees.salary, 1, hr.employees.salary) OVER (
			PARTITION BY hr.employees.job_id
			ORDER BY hr.employees.hire_date, hr.employees.salary DESC
		) <= hr.employees.salary
			THEN 1
		ELSE 0
	END AS inconsistency_flag,
	DENSE_RANK() OVER (
		PARTITION BY hr.employees.job_id
		ORDER BY hr.employees.salary DESC
	) AS salary_sequence_desc
FROM
	hr.employees
	INNER JOIN
	applicable_job
		ON hr.employees.job_id = applicable_job.job_id
ORDER BY
    hr.employees.job_id,
    employment_duration DESC;

Problem 4
Single-order Customers
The company is attempting to understand customer purchasing behavior. Management has noticed that some customers never place an additional order after the first order. In an attempt to understand why, management wishes to acquire a list of the customers that exhibited this behavior. For each customer in the list, the order data is required. Include customer ID, order ID, order date, order total, line-item ID, unit price, and quantity data for each order. In addition to this data, include a line-item total. Line-item total is defined as the product of unit price and quantity for each line-item in the customer’s order. Alias this column as “line_item_total.” Sort the result set by customer ID (ascending) and line-item ID (ascending) for ease of use.

Table(s) Required

oe.orders
oe.order_items

Expected Output
CUSTOMER_IDORDER_IDORDER_DATELINE_ITEM_IDUNIT_PRICEQUANTITYLINE_ITEM_TOTALORDER_TOTAL
119237227-FEB-07 12.22.33.356789 AM148628816447.2
119237227-FEB-07 12.22.33.356789 AM274214816447.2
119237227-FEB-07 12.22.33.356789 AM342729416447.2
119237227-FEB-07 12.22.33.356789 AM4811081016447.2
119237227-FEB-07 12.22.33.356789 AM549613644816447.2
119237227-FEB-07 12.22.33.356789 AM6171728916447.2
119237227-FEB-07 12.22.33.356789 AM7152131516447.2
119237227-FEB-07 12.22.33.356789 AM8303090016447.2
119237227-FEB-07 12.22.33.356789 AM95432172816447.2
119237227-FEB-07 12.22.33.356789 AM10145.2365227.216447.2
120237327-FEB-08 01.34.51.220065 AM1498392416
120237327-FEB-08 01.34.51.220065 AM224124416
121237427-FEB-08 02.41.45.109654 AM11501015004797
121237427-FEB-08 02.41.45.109654 AM27864684797
121237427-FEB-08 02.41.45.109654 AM3781511704797
121237427-FEB-08 02.41.45.109654 AM4792116594797
122237526-FEB-07 03.49.50.459233 AM1421405880103834.4
122237526-FEB-07 03.49.50.459233 AM271845964103834.4
122237526-FEB-07 03.49.50.459233 AM338853230103834.4
122237526-FEB-07 03.49.50.459233 AM4488.48642002.4103834.4
122237526-FEB-07 03.49.50.459233 AM545883960103834.4
122237526-FEB-07 03.49.50.459233 AM617901530103834.4
122237526-FEB-07 03.49.50.459233 AM715931395103834.4
122237526-FEB-07 03.49.50.459233 AM817931581103834.4
122237526-FEB-07 03.49.50.459233 AM945984410103834.4
122237526-FEB-07 03.49.50.459233 AM1030992970103834.4
122237526-FEB-07 03.49.50.459233 AM11361033708103834.4
122237526-FEB-07 03.49.50.459233 AM1213210714124103834.4
122237526-FEB-07 03.49.50.459233 AM1312010913080103834.4
123237607-JUN-07 06.18.08.883310 AM1601484011006.2
123237607-JUN-07 06.18.08.883310 AM2236.5494611006.2
123237607-JUN-07 06.18.08.883310 AM39913128711006.2
123237607-JUN-07 06.18.08.883310 AM47317124111006.2
123237607-JUN-07 06.18.08.883310 AM5133.1212795.111006.2
123237607-JUN-07 06.18.08.883310 AM69525237511006.2
123237607-JUN-07 06.18.08.883310 AM7212756711006.2
123237607-JUN-07 06.18.08.883310 AM8253280011006.2
123237607-JUN-07 06.18.08.883310 AM91.13336.311006.2
123237607-JUN-07 06.18.08.883310 AM103.336118.811006.2
141237707-JUN-07 07.03.01.001100 AM142130546038017.8
141237707-JUN-07 07.03.01.001100 AM21471191749338017.8
141237707-JUN-07 07.03.01.001100 AM3951211149538017.8
141237707-JUN-07 07.03.01.001100 AM425131327538017.8
141237707-JUN-07 07.03.01.001100 AM51.1132145.238017.8
141237707-JUN-07 07.03.01.001100 AM61.1136149.638017.8
142237824-MAY-07 08.59.10.010101 AM1113.320226625691.3
142237824-MAY-07 08.59.10.010101 AM295219025691.3
142237824-MAY-07 08.59.10.010101 AM3438.973072.325691.3
142237824-MAY-07 08.59.10.010101 AM4271129725691.3
142237824-MAY-07 08.59.10.010101 AM5791186925691.3
142237824-MAY-07 08.59.10.010101 AM6217.815326725691.3
142237824-MAY-07 08.59.10.010101 AM74.42511025691.3
142237824-MAY-07 08.59.10.010101 AM8624.8251562025691.3
143238016-MAY-07 09.53.02.909090 AM14226109227132.6
143238016-MAY-07 09.53.02.909090 AM27518135027132.6
143238016-MAY-07 09.53.02.909090 AM3382387427132.6
143238016-MAY-07 09.53.02.909090 AM4488.42411721.627132.6
143238016-MAY-07 09.53.02.909090 AM54628128827132.6
143238016-MAY-07 09.53.02.909090 AM6203060027132.6
143238016-MAY-07 09.53.02.909090 AM7153146527132.6
143238016-MAY-07 09.53.02.909090 AM8173356127132.6
143238016-MAY-07 09.53.02.909090 AM94533148527132.6
143238016-MAY-07 09.53.02.909090 AM103236115227132.6
143238016-MAY-07 09.53.02.909090 AM115237192427132.6
143238016-MAY-07 09.53.02.909090 AM12113.340453227132.6
143238016-MAY-07 09.53.02.909090 AM132.2408827132.6
150238804-JUN-07 04.41.12.554435 PM1431506450282694.3
150238804-JUN-07 04.41.12.554435 PM294908460282694.3
150238804-JUN-07 04.41.12.554435 PM356965376282694.3
150238804-JUN-07 04.41.12.554435 PM41.1105115.5282694.3
150238804-JUN-07 04.41.12.554435 PM52341.9112262292.8282694.3
151238904-JUN-08 05.49.43.546954 PM143180774017620
151238904-JUN-08 05.49.43.546954 PM27318131417620
151238904-JUN-08 05.49.43.546954 PM38021168017620
151238904-JUN-08 05.49.43.546954 PM44622101217620
151238904-JUN-08 05.49.43.546954 PM5153045017620
151238904-JUN-08 05.49.43.546954 PM64633151817620
151238904-JUN-08 05.49.43.546954 PM73443146217620
151238904-JUN-08 05.49.43.546954 PM85247244417620
152239018-NOV-07 04.18.50.546851 PM1144567616.8
152239018-NOV-07 04.18.50.546851 PM2142287616.8
152239018-NOV-07 04.18.50.546851 PM3470.8167532.87616.8
153239127-FEB-06 05.03.03.828330 PM1101550548070.6
153239127-FEB-06 05.03.03.828330 PM2262.93788.748070.6
153239127-FEB-06 05.03.03.828330 PM33487243648070.6
153239127-FEB-06 05.03.03.828330 PM4961.410961448070.6
153239127-FEB-06 05.03.03.828330 PM5551582548070.6
153239127-FEB-06 05.03.03.828330 PM6521893648070.6
153239127-FEB-06 05.03.03.828330 PM71433.32332965.948070.6
154239221-JUL-07 08.59.57.571057 PM14363270926632
154239221-JUL-07 08.59.57.571057 PM27357416126632
154239221-JUL-07 08.59.57.571057 PM33858220426632
154239221-JUL-07 08.59.57.571057 PM47763485126632
154239221-JUL-07 08.59.57.571057 PM54566297026632
154239221-JUL-07 08.59.57.571057 PM62168142826632
154239221-JUL-07 08.59.57.571057 PM71872129626632
154239221-JUL-07 08.59.57.571057 PM84977377326632
154239221-JUL-07 08.59.57.571057 PM94081324026632
155239310-FEB-08 07.53.19.528202 PM1121012023431.9
155239310-FEB-08 07.53.19.528202 PM2295259023431.9
155239310-FEB-08 07.53.19.528202 PM310175508523431.9
155239310-FEB-08 07.53.19.528202 PM43858308023431.9
155239310-FEB-08 07.53.19.528202 PM5260.782085.623431.9
155239310-FEB-08 07.53.19.528202 PM6781078023431.9
155239310-FEB-08 07.53.19.528202 PM721113274323431.9
155239310-FEB-08 07.53.19.528202 PM8108.9141524.623431.9
155239310-FEB-08 07.53.19.528202 PM927819528223431.9
155239310-FEB-08 07.53.19.528202 PM103.31962.723431.9
155239310-FEB-08 07.53.19.528202 PM1169.330207923431.9
156239502-FEB-06 08.19.11.227550 PM13.311036368501
156239502-FEB-06 08.19.11.227550 PM2332.2278969.468501
156239502-FEB-06 08.19.11.227550 PM3788.7302366168501
156239502-FEB-06 08.19.11.227550 PM4690.83423487.268501
156239502-FEB-06 08.19.11.227550 PM5199.1346769.468501
156239502-FEB-06 08.19.11.227550 PM67137262768501
156239502-FEB-06 08.19.11.227550 PM76441262468501
157239819-NOV-07 09.22.53.224175 PM1482.952414.57110.3
157239819-NOV-07 09.22.53.224175 PM2193.6234452.87110.3
157239819-NOV-07 09.22.53.224175 PM39272437110.3
158239919-NOV-07 10.22.38.340990 PM144120528025270.3
158239919-NOV-07 10.22.38.340990 PM29412112825270.3
158239919-NOV-07 10.22.38.340990 PM37615114025270.3
158239919-NOV-07 10.22.38.340990 PM414917253325270.3
158239919-NOV-07 10.22.38.340990 PM5561795225270.3
158239919-NOV-07 10.22.38.340990 PM686.920173825270.3
158239919-NOV-07 10.22.38.340990 PM7222452825270.3
158239919-NOV-07 10.22.38.340990 PM81.12729.725270.3
158239919-NOV-07 10.22.38.340990 PM91.12830.825270.3
158239919-NOV-07 10.22.38.340990 PM1010033330025270.3
158239919-NOV-07 10.22.38.340990 PM11226.6388610.825270.3
159240010-JUL-07 01.34.29.559387 AM152420869286.4
159240010-JUL-07 01.34.29.559387 AM24114169286.4
159240010-JUL-07 01.34.29.559387 AM3123449269286.4
159240010-JUL-07 01.34.29.559387 AM4880161408069286.4
159240010-JUL-07 01.34.29.559387 AM52866.61954465.469286.4
160240110-JUL-07 02.22.53.554822 AM1414164969.2
160240110-JUL-07 02.22.53.554822 AM2268.43805.2969.2
161240202-JUL-07 03.34.44.665170 AM1758600600
162240301-JUL-07 04.49.13.615512 PM1445220220
163240401-JUL-07 04.49.13.664085 PM1856510510
163240401-JUL-07 04.49.13.664085 PM20370510
164240501-JUL-07 04.49.13.678123 PM1137912331233
165240729-JUN-07 07.03.21.526005 AM18554252519
165240729-JUN-07 07.03.21.526005 AM2861815482519
165240729-JUN-07 07.03.21.526005 AM326215462519
166240829-JUN-07 08.59.31.333617 AM1613183309
166240829-JUN-07 08.59.31.333617 AM226126309
166240829-JUN-07 08.59.31.333617 AM31010100309
167240929-JUN-07 09.53.41.984501 AM1684848
168241024-MAY-08 10.19.51.985501 AM1461046045175
168241024-MAY-08 10.19.51.985501 AM240520045175
168241024-MAY-08 10.19.51.985501 AM3120672045175
168241024-MAY-08 10.19.51.985501 AM468854445175
168241024-MAY-08 10.19.51.985501 AM52866.6154299945175
168241024-MAY-08 10.19.51.985501 AM6122125245175
169241124-MAY-07 11.22.10.548639 AM181216215760.5
169241124-MAY-07 11.22.10.548639 AM2208241615760.5
169241124-MAY-07 11.22.10.548639 AM32.2613.215760.5
169241124-MAY-07 11.22.10.548639 AM43.3723.115760.5
169241124-MAY-07 11.22.10.548639 AM573858415760.5
169241124-MAY-07 11.22.10.548639 AM6451149515760.5
169241124-MAY-07 11.22.10.548639 AM77217122415760.5
169241124-MAY-07 11.22.10.548639 AM87517127515760.5
169241124-MAY-07 11.22.10.548639 AM98417142815760.5
169241124-MAY-07 11.22.10.548639 AM10488.4188791.215760.5
169241124-MAY-07 11.22.10.548639 AM11432398915760.5
169241124-MAY-07 11.22.10.548639 AM12152436015760.5
170241229-MAR-06 10.22.09.509801 AM146170782066816
170241229-MAR-06 10.22.09.509801 AM29868666466816
170241229-MAR-06 10.22.09.509801 AM371.568486266816
170241229-MAR-06 10.22.09.509801 AM4492723542466816
170241229-MAR-06 10.22.09.509801 AM51875135066816
170241229-MAR-06 10.22.09.509801 AM62079158066816
170241229-MAR-06 10.22.09.509801 AM71680128066816
170241229-MAR-06 10.22.09.509801 AM83092276066816
170241229-MAR-06 10.22.09.509801 AM95494507666816
Solution
-- Solution 1
WITH single_order_customer AS (
    SELECT
        oe.orders.customer_id,
        COUNT(oe.orders.order_id) AS order_count
    FROM
        oe.orders
    GROUP BY
        oe.orders.customer_id
    HAVING 
        COUNT(oe.orders.order_id) = 1
)
SELECT
    oe.orders.customer_id,
    oe.orders.order_id,
    oe.orders.order_date,
    oe.order_items.line_item_id,
    oe.order_items.unit_price,
    oe.order_items.quantity,
    oe.order_items.unit_price * oe.order_items.quantity AS line_item_total,
    oe.orders.order_total
FROM
    oe.orders
    INNER JOIN
	single_order_customer
        ON oe.orders.customer_id = single_order_customer.customer_id
    INNER JOIN
	oe.order_items
    	ON oe.orders.order_id = oe.order_items.order_id
ORDER BY
    oe.orders.customer_id,
    oe.order_items.line_item_id;

-- Solution 2
SELECT
    oe.orders.customer_id,
    oe.orders.order_id,
    oe.orders.order_date,
    oe.order_items.line_item_id,
    oe.order_items.unit_price,
    oe.order_items.quantity,
    oe.order_items.unit_price * oe.order_items.quantity AS line_item_total,
    oe.orders.order_total
FROM
    oe.orders
    INNER JOIN (
	SELECT
		oe.orders.customer_id,
		COUNT(oe.orders.order_id) AS order_count
	FROM
		oe.orders
	GROUP BY
		oe.orders.customer_id
	HAVING 
		COUNT(oe.orders.order_id) = 1
	) single_order
        ON oe.orders.customer_id = single_order.customer_id
    INNER JOIN
	oe.order_items
    	ON oe.orders.order_id = oe.order_items.order_id
ORDER BY
    oe.orders.customer_id,
    oe.order_items.line_item_id;

Problem 5
Product Category Performance
It’s year-end review time at the company and managers will either be praised or reprimanded for their product categories performance in year 2007. Performance is based on the number of times a product category appeared across all customer orders, not quantity sold. It has been asked of you to generate a report containing the top 5 and bottom 5 product categories. Ties in order count should be assigned the same rank (i.e., 50, 49, 48, 48, 47, 46 -> 1, 2, 3, 3, 4, 5). The category ID, category description, and number of times the product category appeared in year 2007 orders are the required data points. Sort the result set by order count, descending.

Table(s) Required

oe.orders
oe.order_items
oe.product_information
oe.categories_tab

Expected Output
CATEGORY_IDCATEGORY_DESCRIPTIONORDER_COUNT
19miscellaneous hardware (cables, screws, power supplies …)102
16keyboards, mouses, mouse pads48
39miscellaneous office supplies44
15processors, sound and video cards, network cards, motherboards42
32office supplies for daily use (pencils, erasers, staples, …)34
14memory components/upgrades13
24operating systems12
31capitalizable assets (desks, chairs, phones …)9
17other peripherals (CD-ROM, DVD, tape cartridge drives, …)8
13harddisks8
21spreadsheet software2
25software development tools (including languages)2
22word processing software2
Solution
-- Solution 1
WITH category_popularity AS (
    SELECT
    	oe.product_information.category_id,
        oe.categories_tab.category_description,
        COUNT(oe.product_information.category_id) AS order_count,
        DENSE_RANK() OVER (
            ORDER BY COUNT(oe.product_information.category_id)
        ) AS category_popularity_sequence_asc,
        DENSE_RANK() OVER (
            ORDER BY COUNT(oe.product_information.category_id) DESC
        ) AS category_popularity_sequence_desc
    FROM
    	oe.orders
        INNER JOIN
		oe.order_items
            ON oe.orders.order_id = oe.order_items.order_id
        INNER JOIN
		oe.product_information
            ON oe.order_items.product_id = oe.product_information.product_id
        INNER JOIN
		oe.categories_tab
            ON oe.product_information.category_id = oe.categories_tab.category_id
	WHERE
		oe.orders.order_date >= '01-JAN-07'
		AND oe.orders.order_date < '01-JAN-08'
    GROUP BY
    	oe.product_information.category_id,
    	oe.categories_tab.category_description
)
SELECT
    category_popularity.category_id,
	category_popularity.category_description,
	category_popularity.order_count
FROM
	category_popularity
WHERE
    category_popularity.category_popularity_sequence_asc <= 5
    OR category_popularity.category_popularity_sequence_desc <= 5
ORDER BY
    category_popularity.order_count DESC;

-- Solution 2
SELECT
    category_popularity.category_id,
	category_popularity.category_description,
	category_popularity.order_count
FROM (
    SELECT
    	oe.product_information.category_id,
        oe.categories_tab.category_description,
        COUNT(oe.product_information.category_id) AS order_count,
        DENSE_RANK() OVER (
            ORDER BY COUNT(oe.product_information.category_id)
        ) AS category_popularity_sequence_asc,
        DENSE_RANK() OVER (
            ORDER BY COUNT(oe.product_information.category_id) DESC
        ) AS category_popularity_sequence_desc
    FROM
    	oe.orders
        INNER JOIN
		oe.order_items
            ON oe.orders.order_id = oe.order_items.order_id
        INNER JOIN
		oe.product_information
            ON oe.order_items.product_id = oe.product_information.product_id
        INNER JOIN
		oe.categories_tab
            ON oe.product_information.category_id = oe.categories_tab.category_id
	WHERE
		oe.orders.order_date >= '01-JAN-07'
		AND oe.orders.order_date < '01-JAN-08'
    GROUP BY
    	oe.product_information.category_id,
    	oe.categories_tab.category_description
) category_popularity
WHERE
    category_popularity.category_popularity_sequence_asc <= 5
    OR category_popularity.category_popularity_sequence_desc <= 5
ORDER BY
    category_popularity.order_count DESC;

Problem 6
Online Ordering System Adoption
In late 2005, the company heavily invested in developing an online ordering system. The goal was by the end of 2008 for online orders to account for at least 50% of all orders within the year. Management is asking you to generate a report including the number of online orders placed, total number of orders placed across all order modes, and the number of online orders represented as a percentage of all orders for each year. Use the function, ROUND, to round the percentage values to two decimal places. Sort the result set by order year, ascending.

Table(s) Required

oe.orders

Expected Output
ORDER_MODEORDER_YEARMODE_COUNTORDER_COUNTPERCENT_OF_TOTAL
online200621612.5
online2007206928.99
online2008101952.63
Solution
-- Solution 1
WITH yearly_mode_count AS (
	SELECT
		oe.orders.order_mode,
		EXTRACT(YEAR FROM oe.orders.order_date) AS order_year,
		COUNT(oe.orders.order_id) AS order_count
	FROM
		oe.orders
	WHERE
		oe.orders.order_mode = 'online'
	GROUP BY
		oe.orders.order_mode,
		EXTRACT(YEAR FROM oe.orders.order_date)
),
yearly_count AS (
	SELECT
		EXTRACT(YEAR FROM oe.orders.order_date) AS order_year,
		COUNT(oe.orders.order_id) AS order_count
	FROM
		oe.orders
	GROUP BY
		EXTRACT(YEAR FROM oe.orders.order_date)
)
SELECT
	yearly_mode_count.order_mode,
	yearly_mode_count.order_year,
	yearly_mode_count.order_count AS mode_count,
	yearly_count.order_count,
	ROUND((yearly_mode_count.order_count / yearly_count.order_count) * 100, 2) AS percent_of_total
FROM
	yearly_mode_count
	INNER JOIN
	yearly_count
		ON yearly_mode_count.order_year = yearly_count.order_year
ORDER BY
	yearly_mode_count.order_year;

-- Solution 2
SELECT
	yearly_mode_count.order_mode,
	yearly_mode_count.order_year,
	yearly_mode_count.order_count AS mode_count,
	yearly_count.order_count,
	ROUND((yearly_mode_count.order_count / yearly_count.order_count) * 100, 2) AS percent_of_total
FROM (
	SELECT
		oe.orders.order_mode,
		EXTRACT(YEAR FROM oe.orders.order_date) AS order_year,
		COUNT(oe.orders.order_id) AS order_count
	FROM
		oe.orders
	WHERE
		oe.orders.order_mode = 'online'
	GROUP BY
		oe.orders.order_mode,
		EXTRACT(YEAR FROM oe.orders.order_date)
	) yearly_mode_count
	INNER JOIN (
	SELECT
		EXTRACT(YEAR FROM oe.orders.order_date) AS order_year,
		COUNT(oe.orders.order_id) AS order_count
	FROM
		oe.orders
	GROUP BY
		EXTRACT(YEAR FROM oe.orders.order_date) 
	) yearly_count
		ON yearly_mode_count.order_year = yearly_count.order_year
ORDER BY
	yearly_mode_count.order_year;

Problem 7
Top 5 Customers
The company distributes rewards to customers based on the amount spent each year.  Only the top 5 customers are rewarded. Management requires a report containing customer IDs, customer names, order totals across all orders, and customer’s rank for the top 5 customers. Customer rank is based on the sum of all order totals for the customer compared to all other customers’ sums. The customer with the largest amount spent for the year is rank 1, second largest spent for the year is rank 2, and so on. Ties in customer yearly spending will receive the same rank. Use consecutive integers (e.g., 1, 1, 2, 3, 4, 4, 5). Only consider orders placed in year 2008 and format the customer’s name as “last name, first name.” Alias the derived columns with meaningful names. Sort the result set by customer’s sum of order totals, descending.

Table(s) Required

oe.customers
oe.orders

Expected Output
CUSTOMER_IDCUSTOMER_NAMEORDER_TOTALORDER_TOTAL_SEQUENCE
148Steenburgen, Gustav144054.81
101Welles, Constantin82445.62
144Landis, Sivaji711733
149Rampling, Markus600654
104Sutherland, Harrison462575
Solution
-- Solution 1
WITH customer_spending AS (
	SELECT
		oe.customers.customer_id,
		oe.customers.cust_last_name || ', ' || oe.customers.cust_first_name AS customer_name,
		SUM(oe.orders.order_total) AS order_total,
		DENSE_RANK() OVER (ORDER BY SUM(oe.orders.order_total) DESC) AS order_total_sequence
    FROM
		oe.customers
		INNER JOIN
		oe.orders
			ON oe.customers.customer_id = oe.orders.customer_id
	WHERE
		oe.orders.order_date >= '01-JAN-08'
		AND oe.orders.order_date < '01-JAN-09'
    GROUP BY
		oe.customers.customer_id,
        oe.customers.cust_last_name || ', ' || oe.customers.cust_first_name
)
SELECT
    customer_spending.customer_id,
    customer_spending.customer_name,
    customer_spending.order_total,
	customer_spending.order_total_sequence
FROM
	customer_spending
WHERE
	customer_spending.order_total_sequence <= 5
ORDER BY
	customer_spending.order_total DESC;

-- Solution 2
SELECT
    customer_spending.customer_id,
    customer_spending.customer_name,
    customer_spending.order_total,
	customer_spending.order_total_sequence
FROM (
	SELECT
		oe.customers.customer_id,
		oe.customers.cust_last_name || ', ' || oe.customers.cust_first_name AS customer_name,
		SUM(oe.orders.order_total) AS order_total,
		DENSE_RANK() OVER (ORDER BY SUM(oe.orders.order_total) DESC) AS order_total_sequence
    FROM
		oe.customers
		INNER JOIN
		oe.orders
			ON oe.customers.customer_id = oe.orders.customer_id
	WHERE
		oe.orders.order_date >= '01-JAN-08'
		AND oe.orders.order_date < '01-JAN-09'
    GROUP BY
		oe.customers.customer_id,
        oe.customers.cust_last_name || ', ' || oe.customers.cust_first_name
) customer_spending
WHERE
	customer_spending.order_total_sequence <= 5
ORDER BY
	customer_spending.order_total DESC;

Problem 8
Supplier Replacement
The company’s only supplier of operating systems is going out of business, leaving the company only a few weeks to find a new supplier before stock levels hit zero. The company wishes to replace the former supplier with a supplier they already do business with for closely related products. Here, closely related is defined as supplying products in any software category. Management wishes to receive a report containing all suppliers currently supplying software products to the company. In addition to the list of suppliers, include the number of software products each supplier currently supplies. Do not include the supplier going out of business, supplier ID 103092. Sort the supplier list by the number of software products supplied, descending.  HINT: category names starting with the word “software” satisfy the requirement of the supplier being closely related.

Table(s) Required

oe.product_information
oe.categories_tab

Expected Output
SUPPLIER_IDPRODUCT_COUNT
10308910
1030807
1030936
1030884
1030863
1030823
1030942
1030961
1030871
1030831
Solution
SELECT
	oe.product_information.supplier_id,
	COUNT(*) AS product_count
FROM
	oe.product_information
	INNER JOIN
	oe.categories_tab
		ON oe.product_information.category_id = oe.categories_tab.category_id
WHERE
	oe.product_information.supplier_id != '103092'
	AND oe.categories_tab.category_name LIKE 'software%'
GROUP BY
	oe.product_information.supplier_id
ORDER BY
	product_count DESC;

Problem 9
Sales Representative Performance
All sales representatives for the company report to Mary. She has recently mentioned that she would like to see a report containing the number of orders placed by customers assisted by a sales representative in years 2007 and 2008. This task has been assigned to you. Ensure that the report is sorted by order year (ascending), order count (ascending), and sales representative ID (ascending).

Table(s) Required

oe.orders

Expected Output
SALES_REP_IDORDER_YEARORDER_COUNT
15620072
15520073
15820073
15320075
16020075
16320076
15920077
15420078
16120078
15820081
16020081
15520082
15620082
16120083
Solution
SELECT
    oe.orders.sales_rep_id,
    EXTRACT(YEAR FROM oe.orders.order_date) AS order_year,
    COUNT(*) AS order_count
FROM
    oe.orders
WHERE
    oe.orders.sales_rep_id IS NOT NULL
    AND oe.orders.order_date >= '01-JAN-07'
    AND oe.orders.order_date < '01-JAN-09'
GROUP BY
    oe.orders.sales_rep_id,
    EXTRACT(YEAR FROM oe.orders.order_date)
ORDER BY
    order_year,
    order_count,
    oe.orders.sales_rep_id;

Problem 10
Consecutive Top Product Category Performances
It is the beginning of year 2024 and management over the North American sales region is developing a new program to reward product category managers. The reward program is designed to compensate a product category manager when their category performs better than all others for consecutive months. Performance is measured by total sales. To better understand how frequently product category managers will be compensated because of this new program, management is asking you to provide a report containing information on the instances where a product category has generated the most sales for consecutive months in the previous year (i.e., 2023). An instance is defined by a product category generating the most sales in a specific month and the following month. The report should contain the month, product category, and total sale value associated with each instance. Additionally, ensure the report is sorted in ascending order by reporting month.

Table(s) Required

north_america_sale

Expected Output
REPORTING_MONTHPRODUCT_CATEGORYTOTAL_SALE
01-MAR-23Hardware10107952
01-APR-23Hardware9981157
01-AUG-23Software9848671
01-SEP-23Software9532093
01-NOV-23Office Supplies9474652
01-DEC-23Office Supplies10441283
Solution
WITH product_category_performance AS (
    SELECT
        TRUNC(north_america_sale.report_date, 'MONTH') AS reporting_month,
        DENSE_RANK() OVER (
            PARTITION BY TRUNC(north_america_sale.report_date, 'MONTH')
            ORDER BY SUM(north_america_sale.total_sale) DESC
        ) AS product_category_rank,
        north_america_sale.product_category,
        SUM(north_america_sale.total_sale) AS total_sale
    FROM
        north_america_sale
    GROUP BY
        TRUNC(north_america_sale.report_date, 'MONTH'),
        north_america_sale.product_category
),
performance_window AS (
    SELECT
        product_category_performance.reporting_month,
        product_category_performance.product_category_rank,
        product_category_performance.product_category,
        product_category_performance.total_sale,
        LAG(product_category_performance.product_category_rank) OVER (
            PARTITION BY product_category_performance.product_category
            ORDER BY product_category_performance.reporting_month
        ) AS previous_month_rank,
        LEAD(product_category_performance.product_category_rank) OVER (
            PARTITION BY product_category_performance.product_category
            ORDER BY product_category_performance.reporting_month
        ) AS next_month_rank
    FROM
        product_category_performance
)
SELECT
    performance_window.reporting_month,
    performance_window.product_category,
    performance_window.total_sale
FROM
    performance_window
WHERE
    performance_window.product_category_rank = 1
    AND (
        previous_month_rank = 1
        OR next_month_rank = 1
    )
ORDER BY
    performance_window.reporting_month;

Problem 11
Identifying Top Email Domains
Last year, you helped your company launch a website to begin selling their goods and services online. Today you have been asked by your manager, Jane, to develop a means to allow shoppers to create an account and login using their pre-existing email account information. Jane realizes that you cannot solve this problem for every domain used by shoppers, so she would like you to examine the email address data on file supplied by past customers to acquire an idea on which types of domains to focus on based on their popularity among customers. She has requested you to generate a report containing the top two domains based on the number of customers associated with each domain. Ties are to be addressed by assigning the same rank to each domain involved. When a tie occurs, assign the next most popular domain a consecutive rank value (e.g., 1, 1, 2, 2, 3). Sort the report in descending order by the number of email addresses associated with the domains.

Table(s) Required

oe.customers

Expected Output
DOMAINEMAIL_COUNT
DUNLIN.EXAMPLE.COM8
ANHINGA.EXAMPLE.COM7
Solution
WITH domain_extraction AS (
     SELECT
        oe.customers.cust_email,
        SUBSTR(oe.customers.cust_email,
            INSTR(oe.customers.cust_email,'@', 1, 1) + 1,
            LENGTH(oe.customers.cust_email) 
                - INSTR(oe.customers.cust_email,'@', 1, 1)
        ) AS domain
    FROM
        oe.customers
),
domain_popularity AS (
    SELECT
    	domain_extraction.domain,
        COUNT(*) AS email_count,
        DENSE_RANK() OVER (
        	ORDER BY COUNT(*) DESC
        ) AS domain_ranking
    FROM
    	domain_extraction
    GROUP BY
		domain_extraction.domain
)
SELECT
    domain_popularity.domain,
    domain_popularity.email_count
FROM
    domain_popularity
WHERE
    domain_popularity.domain_ranking <= 2
ORDER BY
	domain_popularity.email_count DESC;

Problem 12
Member Type Upgrade
Sonia, the ice cream shop’s manager, is hoping to send each non-platinum member a summary of their purchases via email. She needs each summary to contain the member’s ID, member type, annual member cost, member discount, number of purchases made, amount spent across purchases, and amount saved across purchases. In hopes of persuading members to upgrade to the next member type tier, she also wishes to include the member type, annual member cost, member discount, and the amount saved corresponding to the member type tier one level above the member’s current member tier. She doesn’t want members to have to compute the increased benefit in terms of amount saved, so she needs you to derive the raw increase in the amount each member would have saved with the upgraded member type for them. This is simply the amount saved under the upgraded member type less the original savings. Make the column names report friendly through aliases and sort the result set in ascending order by the members’ current member type ID values.

Table(s) Required

member
member_type
purchase

Expected Output
Member IDMember Type IDMember TypeAnnual Member CostMember DiscountPurchase CountAmount SpentAmount SavedNext-tier Member TypeNext-tier Annual Member CostNext-tier Member DiscountNext-tier Amount SavedIncreased Savings Amount
11Free002170Bronze15.03.51.51
101Free002190Bronze15.03.57.57
251Free00325.50Bronze15.03.77.77
351Free00290Bronze15.03.27.27
481Free002350Bronze15.031.051.05
511Free00117.50Bronze15.03.53.53
541Free001140Bronze15.03.42.42
571Free002270Bronze15.03.81.81
611Free00338.50Bronze15.031.161.16
631Free003300Bronze15.03.9.9
671Free00122.50Bronze15.03.68.68
771Free001210Bronze15.03.63.63
841Free004700Bronze15.032.12.1
881Free002330Bronze15.03.99.99
901Free002300Bronze15.03.9.9
971Free00353.50Bronze15.031.611.61
981Free003650Bronze15.031.951.95
991Free00116.50Bronze15.03.5.5
1001Free002320Bronze15.03.96.96
32Bronze15.03245.61.41Silver20.052.35.94
112Bronze15.03214.55.45Silver20.05.75.3
162Bronze15.03225.22.78Silver20.051.3.52
202Bronze15.03113.59.42Silver20.05.7.28
212Bronze15.03110.19.32Silver20.05.53.21
222Bronze15.03224.25.75Silver20.051.25.5
242Bronze15.03123.28.72Silver20.051.2.48
342Bronze15.0314.85.15Silver20.05.25.1
392Bronze15.03556.751.76Silver20.052.931.17
412Bronze15.0317.76.24Silver20.05.4.16
432Bronze15.0318.73.27Silver20.05.45.18
442Bronze15.03229.59.92Silver20.051.53.61
472Bronze15.03244.141.37Silver20.052.28.91
562Bronze15.03130.56.95Silver20.051.58.63
592Bronze15.03360.151.86Silver20.053.11.24
622Bronze15.03113.58.42Silver20.05.7.28
692Bronze15.03236.861.14Silver20.051.9.76
702Bronze15.03346.561.44Silver20.052.4.96
762Bronze15.0317.76.24Silver20.05.4.16
782Bronze15.03242.691.32Silver20.052.2.88
802Bronze15.0312.91.09Silver20.05.15.06
892Bronze15.0315.82.18Silver20.05.3.12
63Silver20.05350.842.68Gold25.073.751.07
73Silver20.05213.78.73Gold25.071.02.29
123Silver20.05218.05.95Gold25.071.33.38
183Silver20.0515.23.28Gold25.07.39.11
193Silver20.05223.751.25Gold25.071.75.5
263Silver20.0515.23.28Gold25.07.39.11
273Silver20.05439.92.1Gold25.072.94.84
363Silver20.05111.4.6Gold25.07.84.24
403Silver20.05224.71.3Gold25.071.82.52
553Silver20.05216.63.88Gold25.071.23.35
583Silver20.0517.13.38Gold25.07.53.15
643Silver20.05211.4.6Gold25.07.84.24
713Silver20.05457.963.05Gold25.074.271.22
753Silver20.05130.881.63Gold25.072.28.65
813Silver20.05231.351.65Gold25.072.31.66
823Silver20.05343.72.3Gold25.073.22.92
923Silver20.05341.812.2Gold25.073.08.88
953Silver20.05347.032.48Gold25.073.47.99
963Silver20.05358.443.08Gold25.074.311.23
94Gold25.07110.23.77Platinum30.11.1.33
234Gold25.0726.52.49Platinum30.1.7.21
284Gold25.0726.51.49Platinum30.1.7.21
294Gold25.0729.3.7Platinum30.11.3
314Gold25.07366.55.01Platinum30.17.152.14
424Gold25.07222.331.68Platinum30.12.4.72
464Gold25.07233.482.52Platinum30.13.61.08
504Gold25.07433.022.49Platinum30.13.551.06
524Gold25.07222.321.68Platinum30.12.4.72
534Gold25.07341.853.15Platinum30.14.51.35
724Gold25.07130.692.31Platinum30.13.3.99
794Gold25.07236.282.73Platinum30.13.91.17
864Gold25.07219.531.47Platinum30.12.1.63
914Gold25.07218.61.4Platinum30.12.6
934Gold25.0716.51.49Platinum30.1.7.21
Solution
SELECT
	member.member_id AS "Member ID",
	current_member_type.member_type_id AS "Member Type ID",
	current_member_type.description AS "Member Type",
	current_member_type.annual_cost AS "Annual Member Cost",
	current_member_type.discount AS "Member Discount",
	COUNT(purchase.purchase_id) AS "Purchase Count",
	SUM(purchase.purchase_total) AS "Amount Spent",
	ROUND(
		(
			(SUM(purchase.purchase_total)
			/ (1 - current_member_type.discount))
			- SUM(purchase.purchase_total)
		),
		2
	) AS "Amount Saved",
	upgraded_member_type.description AS "Next-tier Member Type",
	upgraded_member_type.annual_cost AS "Next-tier Annual Member Cost",
	upgraded_member_type.discount AS "Next-tier Member Discount",
	ROUND(
		(
			(SUM(purchase.purchase_total)
			/ (1 - current_member_type.discount))
			* upgraded_member_type.discount
		),
		2
	) AS "Next-tier Amount Saved",
	(	
		ROUND(
			(
				(SUM(purchase.purchase_total)
				/ (1 - current_member_type.discount))
				* upgraded_member_type.discount
			),
			2
		) - ROUND(
			(
				(SUM(purchase.purchase_total)
				/ (1 - current_member_type.discount))
				- SUM(purchase.purchase_total)
			),
			2
		)
	) AS "Increased Savings Amount"
FROM
	member
	INNER JOIN
	member_type current_member_type
		ON member.member_type_id = current_member_type.member_type_id
	INNER JOIN
	member_type upgraded_member_type
		ON current_member_type.member_type_id = upgraded_member_type.member_type_id - 1
	INNER JOIN
	purchase
		ON member.member_id = purchase.member_id
GROUP BY
	member.member_id,
	current_member_type.member_type_id,
	current_member_type.description,
	current_member_type.annual_cost,
	current_member_type.discount,
	upgraded_member_type.description,
	upgraded_member_type.annual_cost,
	upgraded_member_type.discount
ORDER BY
	current_member_type.member_type_id;