-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlab05-solutions.sql
More file actions
278 lines (230 loc) · 7.8 KB
/
Copy pathlab05-solutions.sql
File metadata and controls
278 lines (230 loc) · 7.8 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
-- set context
use stackoverflow2010;
-- RECAP OF LECTURE/LAB 4
-- query structure 1
-- order matters! case does not matter
select distinct * -- should duplicate rows be removed? which columns?
from Posts -- which table(?)
where PostTypeId = 1 or PostTypeId = 2 -- filters: =, >, >=, <, <=, !=, <>
-- more: like, ilike, in, between, is null
-- logical operations: and, or, not
order by CreationDate -- ordering columns
limit 1; -- limit number of rows
-- query structure 2
select OwnerUserId, sum(AnswerCount) as NumAnswers,
sum(AnswerCount)/10 as NumAnswersDividedBy10
from Posts
where PostTypeId = 1
group by OwnerUserId
having NumAnswers > 10
order by NumAnswers desc
limit 1;
-- Challenge Lab 4 Solution
--
-- Q1. How many questions in the
-- dataset have accepted answers?
-- Q2. How many questions with the
-- <sql> tag (among other tags) are posted in each year?
-- Q3. On what day of the week are
-- most questions posted?
-- Some more exercises:
--
-- Q. What is the average number of tags used by each
-- user in the questions they ask? Only consider users
-- having at least 50 questions.
select OwnerUserId, avg(nvl(regexp_count(tags, '<'), 0)) as AvgTagCount
from Posts
where PostTypeId = 1
group by OwnerUserId
having count(*) > 50;
-- LECTURE 5
-- Advanced Grouping: Multiple Columns
-- Q. How many posts were created in each month and year?
select year(CreationDate), month(CreationDate), count(*)
from Posts
group by year(CreationDate), month(CreationDate);
-- Advanced Grouping: rollup
-- Q. How many posts were created in each month and year?
-- Also report the year totals and grand total.
select year(CreationDate) y, month(CreationDate) m, count(*) c
from Posts
group by rollup (y, m);
-- Q. How many posts were created in each month and year?
-- Also report the year totals and grand total.
-- Order the results by year and month in increasing order.
select year(CreationDate) y, month(CreationDate) m, count(*) c
from Posts
group by rollup (y, m)
order by (y, m);
-- Q. Replace the NULL cells in the previous result with "TOTAL"
-- Subqueries
-- Which user had the most reputation?
select Id, Reputation
from Users
where Reputation = (select max(Reputation) from Users);
-- Q. Top 3 users with the highest reputation
select Id, Reputation
from Users
where Reputation in (
select Reputation from Users
order by Reputation desc limit 3
);
-- Q. Top 3 users with the most no. of posts
select OwnerUserId, count(*) from Posts
group by OwnerUserId
having OwnerUserId in (
select OwnerUserId
from Posts
group by OwnerUserId
order by count(*) desc
limit 3
);
-- Q. Users who created at least one community wiki
select * from PostTypes;
select OwnerUserId
from Posts p
where exists (
select OwnerUserId
from Posts q
where PostTypeId = 3
and p.OwnerUserId = q.OwnerUserId
);
-- Q. How many posts were created in each month and year?
-- Also report the year totals and grand total.
-- Order the results by year and month in increasing order.
-- Replace the NULL months (not years) in the result with "TOTAL".
--
-- Try: Fix the query below.
select t.y as Year, t.m as Month, t.c
from (
select year(CreationDate) y, month(CreationDate) m, count(*) c
from Posts
group by rollup (y, m)
order by (y, m)
) t;
-- Joins
-- Q. Which user had the largest number of answers accepted?
--
-- Hints: i. The Posts table contains both questions and answers.
--
-- ii. Inspect the AcceptedAnswerID column.
--
-- iii. Is there a way to get the accepted answer and its OwnerUserId
-- for each question from the Posts table? Maybe a self join?
--
-- iv. Once you have done the above, group by the OwnerUserId of the
-- accepted answer and count to get the number of accepted answers
-- by each user
select a.OwnerUserId as AnswererId,
count(*) c
from Posts q
inner join Posts a
on q.AcceptedAnswerId = a.Id
where q.AcceptedAnswerId != 0
and a.PostTypeId = 2
group by AnswererId
order by c desc;
-- Q. Among users who had at least one accepted answer, what is the
-- average number of accepted answers?
--
-- Hint: Convert the query above into a subquery
select avg(c) from (
select count(*) c,
a.OwnerUserId as AnswererId
from Posts q
inner join Posts a
on q.AcceptedAnswerId = a.Id
where q.AcceptedAnswerId != 0
and a.PostTypeId = 2
group by AnswererId
order by c desc
);
-- Q. Can the query above be changed to compute the average
-- number of accepted answers for all users? How?
-- Challenge Lab 5: Write a query to compute the average
-- number of accepted answers over all users in the data.
--
-- Note: This is a difficult query!
-- Q. For each user with at least one accepted answer,
-- report the number of answers they had accepted and
-- their total number of answers
--
-- Hint: Use a correlated subquery in the SELECT statement
-- along with a query you wrote earlier in this lab
select a.OwnerUserId as AnswererId,
count(*) c,
(select count(*) from Posts where OwnerUserId= a.OwnerUserId and PostTypeId = 2) as TotalAnswers
from Posts q
inner join Posts a
on q.AcceptedAnswerId = a.Id
where q.AcceptedAnswerId != 0
and a.PostTypeId = 2
group by AnswererId
order by c desc;
-- Set Operations
-- Q. Report the number of questions tagged with <mysql> and the
-- number of questions tagged with <postgresql> separately
select 'MySQL', count(*) from Posts where tags like '%<mysql>%' and PostTypeId = 1
union all
select 'PostgreSQL', count(*) from Posts where tags like '%<postgresql>%' and PostTypeId = 1;
-- Q. How many questions were tagged with <sql> but not with <mysql>?
select count(*) from (
select Id from Posts where tags like '%<sql>%' and PostTypeId = 1
minus
select Id from Posts where tags like '%<mysql>%' and PostTypeId = 1
);
-- Q. How many questions were tagged with <sql> and <mysql>?
select count(*) from (
select Id from Posts where tags like '%<sql>%' and PostTypeId = 1
intersect
select Id from Posts where tags like '%<mysql>%' and PostTypeId = 1
);
-- Conditional Logic
-- Q. Return the IDs of questions with a new column
-- called EditStatus, set to Edited if the question
-- was edited (LastEditDate is not null) or Never
-- Edited otherwise
select Id, (case when LastEditDate is null then 'Never Edited'
when LastEditDate is not null then 'Edited'
end) as EditStatus
from Posts
where PostTypeId = 1;
-- Q. Report the number of questions with an accepted answer and the number
-- of questions with no accepted answer using a single query
select sum(case when AcceptedAnswerId > 0
then 1
else 0
end) as NumQuestionsWithAccepted,
sum(case when AcceptedAnswerId = 0
then 1
else 0
end) as NumQuestionsWithoutAccepted
from Posts
where PostTypeId = 1;
select count(*) from Posts where PostTypeId = 1 and AcceptedAnswerId > 0
union all
select count(*) from Posts where PostTypeId = 1 and AcceptedAnswerId = 0;
-- Q. Report the number of users with (i) no questions, (ii) between
-- 1 and 100 questions, and (iii) more than 100 questions using
-- a single query without unions
select t.NumPosts, count(*) from
(
select OwnerUserId,
(case when count(*) = 0 then 'None'
when count(*) between 1 and 100 then '<100'
when count(*) > 100 then '>100'
end) as NumPosts
from Posts
where PostTypeId = 1
group by OwnerUserId
) t
group by t.NumPosts;
-- Q. Can you redo the previous query using union?
-- Ranking
select Id, Reputation,
row_number() over (order by Reputation)
from Users;
select Id, Reputation,
rank() over (order by Reputation)
from Users
where Reputation > 3000;