-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathparking_sql_joins.sql
More file actions
373 lines (323 loc) · 14.7 KB
/
parking_sql_joins.sql
File metadata and controls
373 lines (323 loc) · 14.7 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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
-- ============================================================================
-- PARKING APPLICATION - SQL JOINS COMPLETE STUDENT NOTES
-- ============================================================================
-- ============================================================================
-- TABLE CREATION
-- ============================================================================
-- Create Students Table
CREATE TABLE students (
student_id INT PRIMARY KEY,
student_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
phone VARCHAR(15),
year_level VARCHAR(20),
created_date DATE
);
-- Create Parking_Permits Table
CREATE TABLE parking_permits (
permit_id INT PRIMARY KEY,
student_id INT,
vehicle_number VARCHAR(20) NOT NULL,
permit_type VARCHAR(20) NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
fee_amount DECIMAL(10,2),
status VARCHAR(20) DEFAULT 'Active',
FOREIGN KEY (student_id) REFERENCES students(student_id)
);
-- ============================================================================
-- SAMPLE DATA INSERTION (20 Records Each)
-- ============================================================================
-- Insert 20 Students
INSERT INTO students (student_id, student_name, email, phone, year_level, created_date) VALUES
(1, 'John Smith', '[email protected]', '123-456-7890', 'Freshman', '2024-01-15'),
(2, 'Emily Johnson', '[email protected]', '123-456-7891', 'Sophomore', '2024-01-16'),
(3, 'Michael Brown', '[email protected]', '123-456-7892', 'Junior', '2024-01-17'),
(4, 'Sarah Davis', '[email protected]', '123-456-7893', 'Senior', '2024-01-18'),
(5, 'David Wilson', '[email protected]', '123-456-7894', 'Graduate', '2024-01-19'),
(6, 'Lisa Anderson', '[email protected]', '123-456-7895', 'Freshman', '2024-01-20'),
(7, 'James Taylor', '[email protected]', '123-456-7896', 'Sophomore', '2024-01-21'),
(8, 'Maria Garcia', '[email protected]', '123-456-7897', 'Junior', '2024-01-22'),
(9, 'Robert Martinez', '[email protected]', '123-456-7898', 'Senior', '2024-01-23'),
(10, 'Jennifer Lee', '[email protected]', '123-456-7899', 'Graduate', '2024-01-24'),
(11, 'Christopher White', '[email protected]', '123-456-7800', 'Freshman', '2024-01-25'),
(12, 'Amanda Harris', '[email protected]', '123-456-7801', 'Sophomore', '2024-01-26'),
(13, 'Daniel Clark', '[email protected]', '123-456-7802', 'Junior', '2024-01-27'),
(14, 'Jessica Lewis', '[email protected]', '123-456-7803', 'Senior', '2024-01-28'),
(15, 'Matthew Robinson', '[email protected]', '123-456-7804', 'Graduate', '2024-01-29'),
(16, 'Ashley Walker', '[email protected]', '123-456-7805', 'Freshman', '2024-01-30'),
(17, 'Joshua Hall', '[email protected]', '123-456-7806', 'Sophomore', '2024-01-31'),
(18, 'Nicole Young', '[email protected]', '123-456-7807', 'Junior', '2024-02-01'),
(19, 'Andrew King', '[email protected]', '123-456-7808', 'Senior', '2024-02-02'),
(20, 'Samantha Wright', '[email protected]', '123-456-7809', 'Graduate', '2024-02-03');
-- Insert 20 Parking Permits (some students have multiple permits, some have none)
INSERT INTO parking_permits (permit_id, student_id, vehicle_number, permit_type, start_date, end_date, fee_amount, status) VALUES
(101, 1, 'ABC123', 'Standard', '2024-02-01', '2024-05-31', 150.00, 'Active'),
(102, 2, 'XYZ789', 'Premium', '2024-02-01', '2024-05-31', 300.00, 'Active'),
(103, 3, 'DEF456', 'Standard', '2024-02-01', '2024-05-31', 150.00, 'Active'),
(104, 4, 'GHI789', 'Economy', '2024-02-01', '2024-05-31', 75.00, 'Active'),
(105, 5, 'JKL012', 'Premium', '2024-02-01', '2024-05-31', 300.00, 'Active'),
(106, 6, 'MNO345', 'Standard', '2024-02-01', '2024-05-31', 150.00, 'Expired'),
(107, 7, 'PQR678', 'Economy', '2024-02-01', '2024-05-31', 75.00, 'Active'),
(108, 8, 'STU901', 'Premium', '2024-02-01', '2024-05-31', 300.00, 'Active'),
(109, 9, 'VWX234', 'Standard', '2024-02-01', '2024-05-31', 150.00, 'Active'),
(110, 10, 'YZA567', 'Premium', '2024-02-01', '2024-05-31', 300.00, 'Suspended'),
(111, 1, 'ABC124', 'Economy', '2024-03-01', '2024-05-31', 75.00, 'Active'),
(112, 2, 'XYZ790', 'Standard', '2024-03-01', '2024-05-31', 150.00, 'Active'),
(113, 11, 'BCD890', 'Standard', '2024-02-01', '2024-05-31', 150.00, 'Active'),
(114, 12, 'EFG123', 'Economy', '2024-02-01', '2024-05-31', 75.00, 'Active'),
(115, 13, 'HIJ456', 'Premium', '2024-02-01', '2024-05-31', 300.00, 'Active'),
(116, 1, 'KLM789', 'Standard', '2024-02-01', '2024-05-31', 150.00, 'Active'),
(117, 2, 'NOP012', 'Economy', '2024-02-01', '2024-05-31', 75.00, 'Active'),
(118, 3, 'QRS345', 'Premium', '2024-02-01', '2024-05-31', 300.00, 'Expired'),
(119, 4, 'TUV678', 'Standard', '2024-02-01', '2024-05-31', 150.00, 'Active'),
(120,5, 'WXY901', 'Economy', '2024-02-01', '2024-05-31', 75.00, 'Active');
-- ============================================================================
-- STUDENT NOTES: UNDERSTANDING SQL JOINS
-- ============================================================================
/*
WHAT ARE SQL JOINS?
- Joins are used to combine rows from two or more tables based on a related column
- They help us retrieve data that is spread across multiple tables
- The relationship is typically established using foreign keys
TYPES OF JOINS:
1. INNER JOIN - Returns only matching records from both tables
2. LEFT JOIN (LEFT OUTER JOIN) - Returns all records from left table + matching from right
3. RIGHT JOIN (RIGHT OUTER JOIN) - Returns all records from right table + matching from left
4. FULL OUTER JOIN - Returns all records from both tables
5. CROSS JOIN - Returns Cartesian product of both tables
6. SELF JOIN - Joins a table with itself
*/
-- ============================================================================
-- 1. INNER JOIN - Most Common Join Type
-- ============================================================================
-- STUDENT NOTE: INNER JOIN only returns rows where there's a match in BOTH tables
-- Use INNER JOIN when you only want students who HAVE parking permits
SELECT
s.student_id,
s.student_name,
s.email,
s.year_level,
p.permit_id,
p.vehicle_number,
p.permit_type,
p.fee_amount,
p.status
FROM students s
INNER JOIN parking_permits p ON s.student_id = p.student_id;
-- EXPLANATION: This query returns only students who have at least one parking permit
-- Students without permits will NOT appear in results
-- ============================================================================
-- 2. LEFT JOIN - Get All Students (With or Without Permits)
-- ============================================================================
-- STUDENT NOTE: LEFT JOIN returns ALL rows from the left table (students)
-- Even if there's no matching permit, the student will still appear with NULL values
SELECT
s.student_id,
s.student_name,
s.email,
s.year_level,
p.permit_id,
p.vehicle_number,
p.permit_type,
p.fee_amount,
p.status
FROM students s
LEFT JOIN parking_permits p ON s.student_id = p.student_id
ORDER BY s.student_id;
-- EXPLANATION: Shows ALL students. Students without permits show NULL for permit columns
-- This is useful for finding students who DON'T have parking permits
-- Find students WITHOUT parking permits
SELECT
s.student_id,
s.student_name,
s.email,
s.year_level
FROM students s
LEFT JOIN parking_permits p ON s.student_id = p.student_id
WHERE p.student_id IS NULL;
-- ============================================================================
-- 3. RIGHT JOIN - Get All Permits (With or Without Valid Students)
-- ============================================================================
-- STUDENT NOTE: RIGHT JOIN returns ALL rows from the right table (parking_permits)
-- Less commonly used, but useful when you want all permits even if student doesn't exist
SELECT
s.student_id,
s.student_name,
s.email,
p.permit_id,
p.vehicle_number,
p.permit_type,
p.fee_amount,
p.status
FROM students s
RIGHT JOIN parking_permits p ON s.student_id = p.student_id
ORDER BY p.permit_id;
-- EXPLANATION: Shows ALL permits. Permits with invalid student_ids show NULL for student columns
-- This helps identify orphaned permits (permits without valid students)
-- Find permits with invalid student references
SELECT
p.permit_id,
p.student_id,
p.vehicle_number,
p.permit_type
FROM students s
RIGHT JOIN parking_permits p ON s.student_id = p.student_id
WHERE s.student_id IS NULL;
-- ============================================================================
-- 4. FULL OUTER JOIN - Get Everything
-- ============================================================================
-- STUDENT NOTE: FULL OUTER JOIN returns ALL rows from BOTH tables
-- Shows all students (with/without permits) AND all permits (with/without valid students)
SELECT
s.student_id,
s.student_name,
s.email,
p.permit_id,
p.vehicle_number,
p.permit_type,
p.fee_amount,
p.status
FROM students s
FULL OUTER JOIN parking_permits p ON s.student_id = p.student_id
ORDER BY s.student_id, p.permit_id;
-- EXPLANATION: Complete picture - every student and every permit
-- Useful for data auditing and finding mismatched records
-- ============================================================================
-- 5. CROSS JOIN - Cartesian Product (Use with Caution!)
-- ============================================================================
-- STUDENT NOTE: CROSS JOIN creates every possible combination
-- Each student paired with each permit type (usually not what you want!)
-- Example: Show all possible student-permit type combinations
SELECT
s.student_name,
permit_types.type_name,
permit_types.fee
FROM students s
CROSS JOIN (
SELECT 'Standard' as type_name, 150.00 as fee
UNION ALL SELECT 'Premium', 300.00
UNION ALL SELECT 'Economy', 75.00
) permit_types
WHERE s.student_id <= 3 -- Limiting to first 3 students for demo
ORDER BY s.student_name, permit_types.type_name;
-- ============================================================================
-- 6. SELF JOIN - Join Table with Itself
-- ============================================================================
-- STUDENT NOTE: SELF JOIN compares rows within the same table
-- Example: Find students who have the same phone area code
SELECT
s1.student_name as student1,
s2.student_name as student2,
s1.phone as phone1,
s2.phone as phone2
FROM students s1
JOIN students s2 ON SUBSTRING(s1.phone, 1, 3) = SUBSTRING(s2.phone, 1, 3)
AND s1.student_id < s2.student_id -- Avoid duplicate pairs
ORDER BY s1.phone;
-- ============================================================================
-- ADVANCED JOIN EXAMPLES FOR PARKING APPLICATION
-- ============================================================================
-- Example 1: Students with multiple permits
SELECT
s.student_name,
s.email,
COUNT(p.permit_id) as permit_count,
SUM(p.fee_amount) as total_fees
FROM students s
INNER JOIN parking_permits p ON s.student_id = p.student_id
GROUP BY s.student_id, s.student_name, s.email
HAVING COUNT(p.permit_id) > 1
ORDER BY permit_count DESC;
-- Example 2: Revenue by permit type and student year
SELECT
s.year_level,
p.permit_type,
COUNT(p.permit_id) as permit_count,
SUM(p.fee_amount) as total_revenue,
AVG(p.fee_amount) as avg_fee
FROM students s
INNER JOIN parking_permits p ON s.student_id = p.student_id
WHERE p.status = 'Active'
GROUP BY s.year_level, p.permit_type
ORDER BY s.year_level, total_revenue DESC;
-- Example 3: Students by registration month and permit status
SELECT
EXTRACT(MONTH FROM s.created_date) as registration_month,
p.status,
COUNT(*) as count
FROM students s
LEFT JOIN parking_permits p ON s.student_id = p.student_id
GROUP BY EXTRACT(MONTH FROM s.created_date), p.status
ORDER BY registration_month, p.status;
-- ============================================================================
-- PERFORMANCE TIPS FOR JOINS
-- ============================================================================
-- 1. Always use indexes on join columns
CREATE INDEX idx_permits_student_id ON parking_permits(student_id);
CREATE INDEX idx_students_id ON students(student_id);
-- 2. Filter early with WHERE clauses
SELECT s.student_name, p.vehicle_number
FROM students s
INNER JOIN parking_permits p ON s.student_id = p.student_id
WHERE s.year_level = 'Senior'
AND p.status = 'Active'
AND p.permit_type = 'Premium';
-- 3. Use specific column names instead of SELECT *
-- 4. Consider the size of tables when choosing join types
-- ============================================================================
-- COMMON JOIN MISTAKES TO AVOID
-- ============================================================================
/*
1. Forgetting ON clause - Results in Cartesian product
2. Using wrong join type - INNER when you need LEFT JOIN
3. Not handling NULL values properly
4. Joining on non-indexed columns (performance issue)
5. Using SELECT * in large tables
6. Not considering duplicate rows in results
*/
-- ============================================================================
-- PRACTICE QUERIES FOR STUDENTS
-- ============================================================================
-- Query 1: Find all active permits for Graduate students
SELECT
s.student_name,
s.email,
p.vehicle_number,
p.permit_type,
p.fee_amount
FROM students s
INNER JOIN parking_permits p ON s.student_id = p.student_id
WHERE s.year_level = 'Graduate'
AND p.status = 'Active';
-- Query 2: Calculate total parking revenue
SELECT
SUM(fee_amount) as total_revenue,
COUNT(*) as total_permits,
AVG(fee_amount) as average_fee
FROM parking_permits
WHERE status = 'Active';
-- Query 3: Find students who registered in January but don't have permits
SELECT
s.student_name,
s.email,
s.created_date
FROM students s
LEFT JOIN parking_permits p ON s.student_id = p.student_id
WHERE EXTRACT(MONTH FROM s.created_date) = 1
AND p.student_id IS NULL;
-- ============================================================================
-- SUMMARY FOR STUDENTS
-- ============================================================================
/*
KEY TAKEAWAYS:
1. INNER JOIN: Use when you need matching records from both tables
2. LEFT JOIN: Use when you need all records from the left table
3. RIGHT JOIN: Less common, but useful for specific scenarios
4. FULL OUTER JOIN: Use when you need everything from both tables
5. Always consider what data you actually need
6. Test your joins with small datasets first
7. Use proper indexing for better performance
8. Handle NULL values appropriately in your application logic
REMEMBER: The choice of join type dramatically affects your results!
*/