Changes between Version 2 and Version 3 of DatabaseCreation


Ignore:
Timestamp:
06/03/26 02:57:15 (13 days ago)
Author:
231071
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseCreation

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