-
Notifications
You must be signed in to change notification settings - Fork 0
/
1.1.sql
160 lines (140 loc) · 3.19 KB
/
1.1.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
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
-- Get MAX adoption fee
SELECT MAX(Adoption_Fee)
FROM Adoptions;
-- Non correlated expression subquery
SELECT *,
( SELECT MAX(Adoption_Fee)
FROM Adoptions
) AS Max_Fee
FROM Adoptions;
-- Must repeat entire subquery for each instance
SELECT *,
(SELECT MAX(Adoption_Fee) FROM Adoptions) AS Max_Fee,
(((SELECT MAX(Adoption_Fee) FROM Adoptions) - Adoption_Fee) * 100)
/ (SELECT MAX(Adoption_Fee) FROM Adoptions) AS Discount_Percent
FROM Adoptions;
-- Shorten with WITH clause
WITH Adoptions_and_Max_Fee
AS
(
SELECT *,
(SELECT MAX(Adoption_Fee) FROM Adoptions) AS Max_Fee
FROM Adoptions
)
SELECT *,
Max_Fee,
(((Max_Fee - Adoption_Fee) * 100) / Max_Fee) AS Discount_Percent
FROM Adoptions_and_Max_Fee;
-- Use variables
DECLARE @Max_Fee INT = (SELECT MAX(Adoption_Fee) FROM Adoptions);
SELECT *,
@Max_Fee,
(((@Max_Fee - Adoption_Fee) * 100) / @Max_Fee) AS Discount_Percent
FROM Adoptions;
/* PostgreSQL variables...
DROP FUNCTION demo();
CREATE FUNCTION demo()
RETURNS TABLE (
Name VARCHAR(20),
Species VARCHAR(10),
Adoption_Date DATE,
Adoption_Fee SMALLINT,
Max_Adoption_Fee INT,
Discount_Percent INT
)
AS $$
DECLARE Max_Fee INT;
BEGIN
SELECT MAX(adoptions.Adoption_Fee) INTO Max_Fee FROM adoptions;
RETURN QUERY
SELECT a.Name,
a.Species,
a.Adoption_Date,
a.Adoption_Fee,
Max_Fee,
(((Max_Fee - a.Adoption_Fee) * 100) / Max_Fee)
FROM adoptions AS a;
END;
$$ LANGUAGE plpgsql;
SELECT * FROM Demo();
*/
-- Get MAX adoption fee per species
SELECT Species,
MAX(Adoption_Fee) AS Max_Species_Fee
FROM Adoptions
GROUP BY Species;
-- Don't try this at home!
SELECT *,
( SELECT MAX(Adoption_Fee)
FROM Adoptions
WHERE Species = 'Dog'
) AS Max_Dog_Fee,
( SELECT MAX(Adoption_Fee)
FROM Adoptions
WHERE Species = 'Cat'
) AS Max_Cat_Fee,
( SELECT MAX(Adoption_Fee)
FROM Adoptions
WHERE Species = 'Rabbit'
) AS Max_Rabbit_Fee
FROM Adoptions;
-- Correlated expression subquery
SELECT *,
( SELECT MAX(Adoption_Fee)
FROM Adoptions AS A2
WHERE A1.species = A2.Species
) AS Max_Fee
FROM Adoptions AS A1;
-- Better solution, get MAX fee only once per species...
SELECT A.*,
M.Max_Species_Fee
FROM Adoptions AS A
INNER JOIN
(
SELECT Species,
MAX(Adoption_Fee) AS Max_Species_Fee
FROM Adoptions
GROUP BY Species
) AS M
ON A.Species = M.Species;
-- Number of Persons and adoptions
SELECT COUNT(*)
FROM Persons;
SELECT COUNT(*)
FROM Adoptions;
-- Use JOIN
SELECT DISTINCT P.*
FROM Persons AS P
INNER JOIN
Adoptions AS A
ON A.Adopter_Email = P.Email;
-- Use IN = where is the bug?
SELECT *
FROM Persons
WHERE Email IN (SELECT Email FROM Adoptions);
-- Be careful with subquery aliases!
SELECT *
FROM Persons
WHERE Email IN (SELECT Adopter_Email FROM Adoptions);
-- True row expression
/* PostgreSQL
SELECT *
FROM Animals
WHERE (Name, Species) = ROW('Abby', 'Dog');
*/
-- Non correlated EXISTS - Don't try this at home!
SELECT *
FROM Persons
WHERE EXISTS (
SELECT NULL
FROM Adoptions
WHERE species = 'Dog' -- 'Elephant'
);
-- Correlated EXISTS is the way to go!
SELECT *
FROM Persons AS P
WHERE EXISTS (
SELECT NULL
FROM Adoptions AS A
WHERE A.Adopter_Email = P.Email
);