-
Notifications
You must be signed in to change notification settings - Fork 0
/
32_first_and_lastMySQL.sql
73 lines (63 loc) · 2.42 KB
/
32_first_and_lastMySQL.sql
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
use twitterdb
DROP TABLE IF EXISTS personnel CASCADE;
CREATE TABLE personnel(spaceman_id int, job_description text, mission_count int);
INSERT INTO Personnel VALUES
(1001,'Astrogator',6),
(2002,'Astrogator',12),
(3003,'Astrogator',17),
(4004,'Geologist',21),
(5005,'Geologist',9),
(6006,'Geologist',8),
(7007,'Technician',13),
(8008,'Technician',2),
(9009,'Technician',7);
-- My solution
WITH temp AS (
SELECT job_description, MAX(mission_count) AS maximum, MIN(mission_count) AS minimum
FROM personnel
GROUP BY job_description
),
temp2 AS (
SELECT DISTINCT p.job_description,
CASE
WHEN p.job_description = 'Astrogator' AND p.mission_count = t.maximum THEN p.spaceman_id
WHEN p.job_description = 'Geologist' AND p.mission_count = t.maximum THEN p.spaceman_id
WHEN p.job_description = 'Technician' AND p.mission_count = t.maximum THEN p.spaceman_id
END AS most_experienced,
CASE
WHEN p.job_description = 'Astrogator' AND p.mission_count = t.minimum THEN p.spaceman_id
WHEN p.job_description = 'Geologist' AND p.mission_count = t.minimum THEN p.spaceman_id
WHEN p.job_description = 'Technician' AND p.mission_count = t.minimum THEN p.spaceman_id
END AS least_experienced
FROM personnel AS p
INNER JOIN temp AS t
ON t.job_description = p.job_description
)
SELECT job_description,
SUM(COALESCE(most_experienced, 0)) AS most_experienced,
SUM(COALESCE(least_experienced, 0)) AS least_experienced
FROM temp2
GROUP BY job_description;
-- My other, better, solution
WITH rankings AS (
SELECT *,
RANK() OVER (PARTITION BY job_description ORDER BY mission_count DESC) AS rk_desc,
RANK() OVER (PARTITION BY job_description ORDER BY mission_count) AS rk_asc
FROM personnel
)
SELECT job_description,
SUM(CASE
WHEN rk_desc = 1 THEN spaceman_id
ELSE 0
END) AS most_experienced,
SUM(CASE
WHEN rk_asc = 1 THEN spaceman_id
ELSE 0
END) AS least_experienced
FROM rankings
GROUP BY job_description;
-- Their solution
SELECT DISTINCT job_description,
FIRST_VALUE(spaceman_id) OVER (PARTITION BY job_description ORDER BY mission_count DESC) AS most_experienced,
LAST_VALUE(spaceman_id) OVER (PARTITION BY job_description ORDER BY mission_count ASC RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS least_experienced
FROM personnel;