DatabaseCreation: views.sql

File views.sql, 15.7 KB (added by 231071, 7 days ago)
Line 
1
2-- 1. vw_election_results
3
4
5CREATE OR REPLACE VIEW public.vw_election_results AS
6WITH election_totals AS (
7 SELECT vote_result.election_id,
8 sum(vote_result.votes) AS total_valid_votes
9 FROM vote_result
10 GROUP BY vote_result.election_id
11),
12entity_votes AS (
13 SELECT vote_result.election_id,
14 vote_result.entity_id,
15 sum(vote_result.votes) AS total_votes
16 FROM vote_result
17 WHERE vote_result.candidate_id IS NULL
18 GROUP BY vote_result.election_id, vote_result.entity_id
19),
20calc AS (
21 SELECT ev.election_id,
22 ev.entity_id,
23 ev.total_votes,
24 el.total_valid_votes,
25 ev.total_votes::numeric * 100.0 / NULLIF(el.total_valid_votes, 0)::numeric AS vote_pct
26 FROM entity_votes ev
27 JOIN election_totals el USING (election_id)
28)
29SELECT e.election_id,
30 e.name AS election_name,
31 e.election_date,
32 et.type_name AS election_type,
33 pe.entity_id,
34 pe.name AS entity_name,
35 pe.type AS entity_type,
36 c.total_votes,
37 c.total_valid_votes,
38 round(c.vote_pct, 2) AS vote_share_pct,
39 c.vote_pct >= 5.0 AS passed_threshold,
40 wm.method_name AS winner_method
41FROM calc c
42JOIN election e USING (election_id)
43JOIN election_type et ON et.election_type_id = e.election_type_id
44JOIN winner_method wm ON wm.method_id = e.winner_method_id
45JOIN political_entity pe USING (entity_id);
46
47
48-- 2. vw_dhondt_seat_allocation
49
50
51CREATE OR REPLACE VIEW public.vw_dhondt_seat_allocation AS
52WITH district_votes AS (
53 SELECT ed.district_id, ed.election_id, ed.region_id, ed.seats_available,
54 vr.entity_id, sum(vr.votes) AS district_votes
55 FROM electoral_district ed
56 JOIN election e_1 ON e_1.election_id = ed.election_id
57 JOIN vote_result vr ON vr.election_id = ed.election_id
58 JOIN polling_station ps ON ps.station_id = vr.station_id
59 JOIN region r2 ON r2.region_id = ps.municipality_id
60 WHERE e_1.winner_method_id = 8
61 AND vr.candidate_id IS NULL
62 AND (r2.region_id = ed.region_id OR r2.parent_region_id = ed.region_id)
63 GROUP BY ed.district_id, ed.election_id, ed.region_id, ed.seats_available, vr.entity_id
64),
65district_totals AS (
66 SELECT district_id, sum(district_votes) AS total_district_votes FROM district_votes GROUP BY district_id
67),
68eligible AS (
69 SELECT dv.*, dt.total_district_votes,
70 dv.district_votes::numeric * 100.0 / NULLIF(dt.total_district_votes, 0::numeric) AS vote_pct
71 FROM district_votes dv JOIN district_totals dt USING (district_id)
72 WHERE (dv.district_votes::numeric * 100.0 / NULLIF(dt.total_district_votes, 0::numeric)) >= 5.0
73),
74dhondt AS (
75 SELECT e_1.*, d.divisor,
76 e_1.district_votes::numeric / d.divisor::numeric AS quotient
77 FROM eligible e_1 CROSS JOIN LATERAL generate_series(1, e_1.seats_available) d(divisor)
78),
79ranked AS (
80 SELECT *, rank() OVER (PARTITION BY district_id ORDER BY quotient DESC) AS rn FROM dhondt
81),
82seats AS (
83 SELECT district_id, election_id, region_id, seats_available, entity_id,
84 district_votes, total_district_votes, vote_pct,
85 count(*) FILTER (WHERE rn <= seats_available) AS seats_won
86 FROM ranked
87 GROUP BY district_id, election_id, region_id, seats_available, entity_id,
88 district_votes, total_district_votes, vote_pct
89)
90SELECT s.election_id, e.name AS election_name, e.election_date,
91 s.district_id, r.name AS region_name, s.seats_available,
92 s.entity_id, pe.name AS entity_name, pe.type AS entity_type,
93 s.district_votes AS total_votes, s.total_district_votes,
94 round(s.vote_pct, 2) AS vote_share_pct, s.seats_won
95FROM seats s
96JOIN election e USING (election_id)
97JOIN region r ON r.region_id = s.region_id
98JOIN political_entity pe USING (entity_id)
99ORDER BY s.election_id, s.district_id, s.seats_won DESC;
100
101
102-- 3. vw_invalid_ballot_analysis
103
104
105CREATE OR REPLACE VIEW public.vw_invalid_ballot_analysis AS
106SELECT e.election_id,
107 e.name AS election_name,
108 r.region_id,
109 r.name AS region_name,
110 count(*) AS total_ballots,
111 count(*) FILTER (WHERE NOT b.is_valid) AS invalid_ballots,
112 round(count(*) FILTER (WHERE NOT b.is_valid)::numeric * 100.0
113 / NULLIF(count(*), 0)::numeric, 2) AS invalid_pct
114FROM ballot b
115JOIN election e ON e.election_id = b.election_id
116JOIN polling_station ps ON ps.station_id = b.station_id
117JOIN region r ON r.region_id = ps.municipality_id
118GROUP BY e.election_id, e.name, r.region_id, r.name;
119
120
121-- 4. vw_local_election_winners
122
123
124CREATE OR REPLACE VIEW public.vw_local_election_winners AS
125WITH totalvotesperparty AS (
126 SELECT vr.election_id, e.name AS election_name, r.name AS municipality_name,
127 pe.name AS party_name, sum(vr.votes) AS total_sum_votes
128 FROM vote_result vr
129 JOIN election e ON vr.election_id = e.election_id
130 JOIN political_entity pe ON vr.entity_id = pe.entity_id
131 JOIN polling_station ps ON vr.station_id = ps.station_id
132 JOIN region r ON ps.municipality_id = r.region_id
133 WHERE e.election_type_id = 3
134 GROUP BY vr.election_id, e.name, r.name, pe.name
135),
136rankedwinners AS (
137 SELECT *, rank() OVER (PARTITION BY election_id, municipality_name ORDER BY total_sum_votes DESC) AS rnk
138 FROM totalvotesperparty
139)
140SELECT election_name, municipality_name,
141 party_name AS winner_name,
142 total_sum_votes AS votes_received,
143 'Winner'::text AS status
144FROM rankedwinners
145WHERE rnk = 1;
146
147
148-- 5. vw_parliamentary_municipality_winners
149
150
151CREATE OR REPLACE VIEW public.vw_parliamentary_municipality_winners AS
152WITH aggregatedvotes AS (
153 SELECT e.election_id, e.name AS election_name, r.name AS municipality_name,
154 pe.name AS party_name, sum(vr.votes) AS total_votes
155 FROM vote_result vr
156 JOIN election e ON vr.election_id = e.election_id
157 JOIN political_entity pe ON vr.entity_id = pe.entity_id
158 JOIN polling_station ps ON vr.station_id = ps.station_id
159 JOIN region r ON ps.municipality_id = r.region_id
160 WHERE e.election_type_id = 2
161 GROUP BY e.election_id, e.name, r.name, pe.name
162),
163rankedwinners AS (
164 SELECT *, rank() OVER (PARTITION BY election_id, municipality_name ORDER BY total_votes DESC) AS pos
165 FROM aggregatedvotes
166)
167SELECT election_name, municipality_name,
168 party_name AS dominant_party,
169 total_votes AS winning_votes,
170 'Municipality Winner'::text AS status
171FROM rankedwinners
172WHERE pos = 1;
173
174
175-- 6. vw_party_demographic_performance
176
177
178CREATE OR REPLACE VIEW public.vw_party_demographic_performance AS
179WITH VoterDemographics AS (
180
181 SELECT
182 ve.election_id,
183 ve.station_id,
184 p.date_of_birth,
185 EXTRACT(YEAR FROM p.date_of_birth) as birth_year
186 FROM public.voter_election ve
187 JOIN public.voter v ON ve.voter_id = v.voter_id
188 JOIN public.person p ON v.person_id = p.person_id
189),
190BallotStats AS (
191
192 SELECT
193 b.election_id,
194 b.station_id,
195 b.entity_id,
196 b.ballot_id
197 FROM public.ballot b
198 WHERE b.is_valid = true
199)
200SELECT
201 e.name AS election_name,
202 r.name AS region_name,
203 pe.name AS party_name,
204 ps.name AS station_name,
205
206 COALESCE(COUNT(CASE WHEN vd.birth_year >= 1996 THEN 1 END), 0) AS gen_z_votes,
207 COALESCE(COUNT(CASE WHEN vd.birth_year >= 1981 AND vd.birth_year <= 1995 THEN 1 END), 0) AS millennial_votes,
208 COALESCE(COUNT(CASE WHEN vd.birth_year < 1981 THEN 1 END), 0) AS senior_votes,
209 COUNT(bs.ballot_id) AS total_valid_votes
210FROM BallotStats bs
211JOIN public.election e ON bs.election_id = e.election_id
212JOIN public.polling_station ps ON bs.station_id = ps.station_id
213JOIN public.region r ON ps.municipality_id = r.region_id
214JOIN public.political_entity pe ON bs.entity_id = pe.entity_id
215
216LEFT JOIN VoterDemographics vd ON bs.election_id = vd.election_id
217 AND bs.station_id = vd.station_id
218GROUP BY e.name, r.name, pe.name, ps.name;
219
220
221-- 7. vw_party_performance_over_time
222
223
224CREATE OR REPLACE VIEW public.vw_party_performance_over_time AS
225WITH party_votes AS (
226 SELECT e.election_id, e.name AS election_name, e.election_date,
227 pe.entity_id, pe.name AS entity_name, sum(vr.votes) AS total_votes
228 FROM vote_result vr
229 JOIN election e ON e.election_id = vr.election_id
230 JOIN political_entity pe ON pe.entity_id = vr.entity_id
231 WHERE vr.candidate_id IS NULL
232 GROUP BY e.election_id, e.name, e.election_date, pe.entity_id, pe.name
233),
234totals AS (
235 SELECT election_id, sum(total_votes) AS total_election_votes FROM party_votes GROUP BY election_id
236)
237SELECT pv.election_id, pv.election_name, pv.election_date,
238 pv.entity_id, pv.entity_name, pv.total_votes, t.total_election_votes,
239 round(pv.total_votes::numeric * 100.0 / NULLIF(t.total_election_votes, 0::numeric), 2) AS vote_share_pct
240FROM party_votes pv JOIN totals t USING (election_id)
241ORDER BY pv.entity_name, pv.election_date;
242
243
244-- 8. vw_polling_station_stats
245
246
247CREATE OR REPLACE VIEW public.vw_polling_station_stats AS
248SELECT e.election_id,
249 e.name AS election_name,
250 ps.station_id,
251 ps.name AS station_name,
252 count(DISTINCT v.voter_id) AS registered_voters,
253 count(b.ballot_id) AS ballots_cast,
254 count(b.ballot_id) FILTER (WHERE b.is_valid) AS valid_ballots,
255 count(b.ballot_id) FILTER (WHERE NOT b.is_valid) AS invalid_ballots,
256 round(count(b.ballot_id)::numeric * 100.0
257 / NULLIF(count(DISTINCT v.voter_id), 0)::numeric, 2) AS turnout_pct
258FROM polling_station ps
259JOIN station_election se ON se.station_id = ps.station_id
260JOIN election e ON e.election_id = se.election_id
261LEFT JOIN ballot b ON b.station_id = ps.station_id AND b.election_id = e.election_id
262LEFT JOIN voter v ON v.station_id = ps.station_id
263GROUP BY e.election_id, e.name, ps.station_id, ps.name;
264
265
266-- 9. vw_polling_station_voter_count
267
268
269CREATE OR REPLACE VIEW public.vw_polling_station_voter_count AS
270SELECT r.name AS region_name,
271 ps.name AS station_name,
272 count(v.voter_id) AS actual_registered_voters
273FROM polling_station ps
274JOIN region r ON ps.municipality_id = r.region_id
275LEFT JOIN voter v ON ps.station_id = v.station_id
276GROUP BY r.name, ps.name;
277
278
279-- 10. vw_presidential_by_municipality
280
281
282CREATE OR REPLACE VIEW public.vw_presidential_by_municipality AS
283WITH cityvotes AS (
284 SELECT e.name AS election_name, r.name AS municipality_name,
285 pe.name AS candidate_name, sum(vr.votes) AS total_votes
286 FROM vote_result vr
287 JOIN election e ON vr.election_id = e.election_id
288 JOIN political_entity pe ON vr.entity_id = pe.entity_id
289 JOIN polling_station ps ON vr.station_id = ps.station_id
290 JOIN region r ON ps.municipality_id = r.region_id
291 WHERE e.election_type_id = 1
292 GROUP BY e.name, r.name, pe.name
293),
294rankedcities AS (
295 SELECT *, rank() OVER (PARTITION BY election_name, municipality_name ORDER BY total_votes DESC) AS pos
296 FROM cityvotes
297)
298SELECT election_name, municipality_name, candidate_name,
299 total_votes, 'City Winner'::text AS level
300FROM rankedcities
301WHERE pos = 1;
302
303
304-- 11. vw_regional_voting_patterns
305
306
307CREATE OR REPLACE VIEW public.vw_regional_voting_patterns AS
308WITH regionhierarchy AS (
309 SELECT ps.station_id,
310 r.name AS municipality_name,
311 parent.name AS sub_region_name,
312 grandparent.name AS country_name
313 FROM polling_station ps
314 JOIN region r ON ps.municipality_id = r.region_id
315 LEFT JOIN region parent ON r.parent_region_id = parent.region_id
316 LEFT JOIN region grandparent ON parent.parent_region_id = grandparent.region_id
317),
318candidatevotes AS (
319 SELECT e.election_id, e.name AS election_name, e.election_type_id,
320 pe.name AS candidate_name,
321 CASE WHEN e.election_type_id = 1 THEN rh.country_name ELSE rh.municipality_name END AS final_region,
322 sum(vr.votes) AS total_votes_sum
323 FROM vote_result vr
324 JOIN election e ON vr.election_id = e.election_id
325 JOIN political_entity pe ON vr.entity_id = pe.entity_id
326 JOIN regionhierarchy rh ON vr.station_id = rh.station_id
327 GROUP BY e.election_id, e.name, e.election_type_id, pe.name,
328 CASE WHEN e.election_type_id = 1 THEN rh.country_name ELSE rh.municipality_name END
329),
330rankedwinners AS (
331 SELECT *, rank() OVER (PARTITION BY election_id, final_region ORDER BY total_votes_sum DESC) AS rnk
332 FROM candidatevotes
333)
334SELECT election_name, final_region AS region_name,
335 candidate_name AS dominant_entity,
336 total_votes_sum AS winning_votes,
337 'Winner'::text AS status
338FROM rankedwinners
339WHERE rnk = 1 AND final_region IS NOT NULL;
340
341
342-- 12. vw_voter_turnout
343
344
345CREATE OR REPLACE VIEW public.vw_voter_turnout AS
346WITH registered AS (
347 SELECT se.election_id, ps.municipality_id AS region_id,
348 sum(ps.registered_voter) AS registered_voters
349 FROM station_election se JOIN polling_station ps ON ps.station_id = se.station_id
350 GROUP BY se.election_id, ps.municipality_id
351),
352ballots AS (
353 SELECT b.election_id, ps.municipality_id AS region_id,
354 count(*) AS ballots_cast,
355 count(*) FILTER (WHERE b.is_valid) AS valid_ballots,
356 count(*) FILTER (WHERE NOT b.is_valid) AS invalid_ballots
357 FROM ballot b JOIN polling_station ps ON ps.station_id = b.station_id
358 GROUP BY b.election_id, ps.municipality_id
359),
360combined AS (
361 SELECT COALESCE(r.election_id, b.election_id) AS election_id,
362 COALESCE(r.region_id, b.region_id) AS region_id,
363 r.registered_voters,
364 b.ballots_cast, b.valid_ballots, b.invalid_ballots,
365 b.ballots_cast::numeric * 100.0 / NULLIF(r.registered_voters, 0)::numeric AS turnout_pct_raw,
366 b.invalid_ballots::numeric * 100.0 / NULLIF(b.ballots_cast, 0)::numeric AS invalid_pct_raw
367 FROM registered r FULL JOIN ballots b ON r.election_id = b.election_id AND r.region_id = b.region_id
368)
369SELECT e.election_id, e.name AS election_name, e.election_date,
370 et.type_name AS election_type,
371 c.region_id, rg.name AS region_name,
372 COALESCE(c.registered_voters, 0::bigint) AS registered_voters,
373 COALESCE(c.ballots_cast, 0::bigint) AS ballots_cast,
374 COALESCE(c.valid_ballots, 0::bigint) AS valid_ballots,
375 COALESCE(c.invalid_ballots, 0::bigint) AS invalid_ballots,
376 round(c.turnout_pct_raw, 2) AS turnout_pct,
377 round(c.invalid_pct_raw, 2) AS invalid_pct
378FROM combined c
379JOIN election e USING (election_id)
380JOIN election_type et ON et.election_type_id = e.election_type_id
381JOIN region rg ON rg.region_id = c.region_id
382WHERE c.registered_voters IS NOT NULL OR c.ballots_cast IS NOT NULL
383ORDER BY e.election_date, round(c.turnout_pct_raw, 2) DESC;