Repository navigation
Expand file tree
/
Copy path17_Window_Value_Functions.sql
More file actions
86 lines (78 loc) · 3.2 KB
/
Copy path17_Window_Value_Functions.sql
File metadata and controls
86 lines (78 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* ==============================================================================
SQL Window Value Functions
---------------------------------------------------------------------------------
These functions let you reference and compare values from other rows
in a result set without complex joins or subqueries, enabling advanced
analysis on ordered data.
Table of Contents:
1. LEAD, LAG
2. FIRST_VALUE, LAST_VALUE
=================================================================================
*/
-- Run this line first: every query in this script uses SalesDB
USE SalesDB;
/* ==============================================================================
1. LEAD, LAG
============================================================================== */
/* TASK 1:
Analyze the Month-over-Month Performance by Finding the Percentage Change in Sales
Between the Current and Previous Months
*/
SELECT
*,
CurrentMonthSales - PreviousMonthSales AS MoM_Change,
ROUND(
CAST((CurrentMonthSales - PreviousMonthSales) AS FLOAT)
/ PreviousMonthSales * 100, 1
) AS MoM_Perc
FROM (
SELECT
MONTH(OrderDate) AS OrderMonth,
SUM(Sales) AS CurrentMonthSales,
LAG(SUM(Sales)) OVER (ORDER BY MONTH(OrderDate)) AS PreviousMonthSales
FROM Sales.Orders
GROUP BY MONTH(OrderDate)
) AS MonthlySales;
/* TASK 2:
Customer Loyalty Analysis - Rank Customers Based on the Average Days Between Their Orders
*/
SELECT
CustomerID,
AVG(DaysUntilNextOrder) AS AvgDays,
-- 999999 puts customers with only one order (their average is NULL) at the end of the ranking.
-- The cleaner way (NULL Functions, Task 3):
-- ORDER BY CASE WHEN AVG(DaysUntilNextOrder) IS NULL THEN 1 ELSE 0 END, AVG(DaysUntilNextOrder)
RANK() OVER (ORDER BY COALESCE(AVG(DaysUntilNextOrder), 999999)) AS RankAvg
FROM (
SELECT
OrderID,
CustomerID,
OrderDate AS CurrentOrder,
LEAD(OrderDate) OVER (PARTITION BY CustomerID ORDER BY OrderDate) AS NextOrder,
DATEDIFF(
day,
OrderDate,
LEAD(OrderDate) OVER (PARTITION BY CustomerID ORDER BY OrderDate)
) AS DaysUntilNextOrder
FROM Sales.Orders
) AS CustomerOrdersWithNext
GROUP BY CustomerID;
/* ==============================================================================
2. FIRST_VALUE, LAST_VALUE
============================================================================== */
/* TASK 3:
Find the Lowest and Highest Sales for Each Product,
and determine the difference between the current Sales and the lowest Sales for each Product.
*/
SELECT
OrderID,
ProductID,
Sales,
FIRST_VALUE(Sales) OVER (PARTITION BY ProductID ORDER BY Sales) AS LowestSales,
LAST_VALUE(Sales) OVER (
PARTITION BY ProductID
ORDER BY Sales
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS HighestSales,
Sales - FIRST_VALUE(Sales) OVER (PARTITION BY ProductID ORDER BY Sales) AS SalesDifference
FROM Sales.Orders;