-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path09-joins.sql
More file actions
142 lines (131 loc) · 3.35 KB
/
Copy path09-joins.sql
File metadata and controls
142 lines (131 loc) · 3.35 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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
-- Lesson 09: Join Patterns
-- Goal: learn the most common join types and how to avoid bad join logic.
-- 1. Build small normalized practice tables.
DROP TABLE IF EXISTS lesson_join_order_items;
DROP TABLE IF EXISTS lesson_join_orders;
DROP TABLE IF EXISTS lesson_join_customers;
DROP TABLE IF EXISTS lesson_join_products;
CREATE TABLE lesson_join_customers AS
SELECT DISTINCT ON (customer_id)
customer_id,
customer_name,
region
FROM superstore
ORDER BY customer_id, order_date
LIMIT 12;
CREATE TABLE lesson_join_orders AS
SELECT DISTINCT ON (s.order_id)
s.order_id,
s.customer_id,
s.order_date
FROM superstore s
JOIN lesson_join_customers c
ON s.customer_id = c.customer_id
ORDER BY s.order_id, s.order_date
LIMIT 20;
CREATE TABLE lesson_join_order_items AS
SELECT
row_id,
order_id,
product_id,
sales,
quantity,
profit
FROM superstore
WHERE order_id IN (
SELECT order_id
FROM lesson_join_orders
)
LIMIT 40;
CREATE TABLE lesson_join_products AS
WITH matched_products AS (
SELECT DISTINCT ON (s.product_id)
s.product_id,
s.product_name,
s.category
FROM superstore s
JOIN lesson_join_order_items oi
ON s.product_id = oi.product_id
ORDER BY s.product_id, s.order_date
),
extra_products AS (
SELECT DISTINCT ON (s.product_id)
s.product_id,
s.product_name,
s.category
FROM superstore s
WHERE NOT EXISTS (
SELECT 1
FROM matched_products mp
WHERE mp.product_id = s.product_id
)
ORDER BY s.product_id, s.order_date
LIMIT 5
)
SELECT *
FROM matched_products
UNION ALL
SELECT *
FROM extra_products;
-- 2. INNER JOIN returns matched rows only.
SELECT
o.order_id,
c.customer_name,
c.region,
o.order_date
FROM lesson_join_orders o
JOIN lesson_join_customers c
ON o.customer_id = c.customer_id
ORDER BY o.order_date, o.order_id;
-- 3. LEFT JOIN keeps all rows from the left table.
SELECT
p.product_id,
p.product_name,
COUNT(oi.row_id) AS item_count
FROM lesson_join_products p
LEFT JOIN lesson_join_order_items oi
ON p.product_id = oi.product_id
GROUP BY p.product_id, p.product_name
ORDER BY item_count, p.product_name;
-- 4. Self join compares rows within the same table.
SELECT
a.customer_id,
a.customer_name AS customer_a,
b.customer_name AS customer_b,
a.region
FROM lesson_join_customers a
JOIN lesson_join_customers b
ON a.region = b.region
AND a.customer_id < b.customer_id
ORDER BY a.region, a.customer_name, b.customer_name;
-- 5. Anti join finds rows with no match.
SELECT
p.product_id,
p.product_name
FROM lesson_join_products p
LEFT JOIN lesson_join_order_items oi
ON p.product_id = oi.product_id
WHERE oi.product_id IS NULL
ORDER BY p.product_name;
-- 6. Example of a risky join that can duplicate rows if the key is wrong.
SELECT
c.region,
COUNT(*) AS joined_rows
FROM lesson_join_customers c
JOIN lesson_join_products p
ON c.region = c.region
GROUP BY c.region
ORDER BY c.region;
-- 7. Correct the logic by joining on real related keys.
SELECT
c.customer_name,
p.product_name,
oi.sales
FROM lesson_join_order_items oi
JOIN lesson_join_orders o
ON oi.order_id = o.order_id
JOIN lesson_join_customers c
ON o.customer_id = c.customer_id
JOIN lesson_join_products p
ON oi.product_id = p.product_id
ORDER BY oi.sales DESC, c.customer_name;