PostgreSQL and Querying Pokémon
Install (Lessons Learned)
I installed PostgreSQL directly from the website here. I also immediately downloaded the corresponding documentation from here. After installing in my local ‘C:\Program Files’ folder, I ran into an odd issue where I could not log into the default user in psql, which also happened to not be the postgre default user. After opening pgAdmin4 and reading the logs found in data/logs/, the solution was to add both a Database and Login/Group Role with the same name as the user defaulting in. This allowed me to finally ‘log in’ to psql.
Overall, I found the overall query writing experience to be better using pgAdmin directly, than trying to write in psql command line. I have used MS SQL in the past, so the Query Tool within pgAdmin was very familiar. It is also useful see the tables and views directly in your database.
Using Window Function to Find Pokémon First Type Ranking Based on Total Base Points
In order to accommodate multiple typing, I decided to do do two average window functions over the two types and then average the two results. Although a perfect measurement, averaging the total_points of the two types and then taking the average of that number still gives insight into how powerful a Pokémon is comparatively to other Pokémon with the same type 1 and type 2 typing. The results were then sorted by the first Pokémon type.
WITH pkmn_win as (SELECT pokedex_number, name, type_1, type_2, total_points,
AVG(total_points) OVER(PARTITION BY type_1) as avg_type1,
AVG(total_points) OVER(PARTITION BY type_2) as avg_type2,
rank() OVER (PARTITION BY type_1 ORDER BY total_points DESC) type_rnk
FROM pkmn
ORDER BY pokedex_number)
SELECT
pokedex_number, name, type_1, type_2, total_points,
(avg_type1 + avg_type2)/2 as avg_avg,
rank() OVER (PARTITION BY ((avg_type1 + avg_type2)/2) ORDER BY total_points DESC) avg_rnk
FROM pkmn_win
Top 15 Results:
| pd_number | name | type_1 | type_2 | total_points | avg_avg | avg_rnk |
|---|---|---|---|---|---|---|
| 15 | Mega Beedrill | Bug | Poison | 495 | 393.8481156595191683 | 1 |
| 545 | Scolipede | Bug | Poison | 485 | 393.8481156595191683 | 2 |
| 49 | Venomoth | Bug | Poison | 450 | 393.8481156595191683 | 3 |
| 168 | Ariados | Bug | Poison | 400 | 393.8481156595191683 | 4 |
| 15 | Beedrill | Bug | Poison | 395 | 393.8481156595191683 | 5 |
| 269 | Dustox | Bug | Poison | 385 | 393.8481156595191683 | 6 |
| 544 | Whirlipede | Bug | Poison | 360 | 393.8481156595191683 | 7 |
| 48 | Venonat | Bug | Poison | 305 | 393.8481156595191683 | 8 |
| 543 | Venipede | Bug | Poison | 260 | 393.8481156595191683 | 9 |
| 167 | Spinarak | Bug | Poison | 250 | 393.8481156595191683 | 10 |
| 14 | Kakuna | Bug | Poison | 205 | 393.8481156595191683 | 11 |
| 13 | Weedle | Bug | Poison | 195 | 393.8481156595191683 | 12 |
| 127 | Pinsir | Bug | None | 500 | 397.6944444444444445 | 1 |
| 617 | Accelgor | Bug | None | 495 | 397.6944444444444445 | 2 |
| 314 | Illumise | Bug | None | 430 | 397.6944444444444445 | 3 |
Finding Total Count of Pokémon with a Unique Type Combination
There are 18 Pokémon types; however, the second typing (type 2) can technically have 19 unique value, due to no secondary typing requirements. For this reason, types were concatenated in their ‘forward’ position (type 1, type 2) and their ‘backwards’ position (type 2, type 1), and then counted in separate CTEs. The results were joined on the backwards concatenation to ensure all type combinations were present. The separate count columns were then summed to get the overall count.
with bkwd as (
select
count(pokedex_number) count_bkw,
concat(type_2,',',type_1) as bkw
from pkmn
group by bkw
),
fwrd as (select
count(pokedex_number) count_fwd,
concat(type_1,',',type_2) as fwd
from pkmn
group by fwd
)
select
bkwd.bkw as grp,
bkwd.count_bkw as count_bkw,
(case when(fwrd.count_fwd is null) then 0 else fwrd.count_fwd end) as count_fwd,
(bkwd.count_bkw + (case when(fwrd.count_fwd is null) then 0 else fwrd.count_fwd end)) as ttl
from bkwd
left outer join fwrd on fwrd.fwd = bkwd.bkw
order by ttl desc
Top 15 Results:
| grp | count_bkw | count_fwd | ttl |
|---|---|---|---|
| None,Water | 72 | 0 | 72 |
| None,Normal | 71 | 0 | 71 |
| None,Psychic | 44 | 0 | 44 |
| None,Grass | 43 | 0 | 43 |
| None,Fire | 34 | 0 | 34 |
| None,Electric | 33 | 0 | 33 |
| None,Fighting | 28 | 0 | 28 |
| Flying,Normal | 27 | 0 | 27 |
| None,Bug | 19 | 0 | 19 |
| None,Ice | 19 | 0 | 19 |
| None,Fairy | 19 | 0 | 19 |
| None,Ground | 17 | 0 | 17 |
| None,Rock | 16 | 0 | 16 |
| None,Poison | 16 | 0 | 16 |
| Poison,Grass | 15 | 0 | 15 |
| Flying,Bug | 14 | 0 | 14 |
Returning List of Pokémon with a Unique Type Combination
To select the Pokémon with the most common typing, the previous query was put into another CTE and filtered in a WHERE clause against the complete data.
with bkwd as (
select
count(pokedex_number) count_bkw,
concat(type_2,',',type_1) as bkw
from pkmn
group by bkw
),
fwrd as (select
count(pokedex_number) count_fwd,
concat(type_1,',',type_2) as fwd
from pkmn
group by fwd
),
rnk as (select
bkwd.bkw as grp,
bkwd.count_bkw as count_bkw,
fwrd.count_fwd as count_fwd,
(bkwd.count_bkw + (case when(fwrd.count_fwd is null) then 0 else fwrd.count_fwd end)) as ttl,
rank () OVER(order by (bkwd.count_bkw + (case when(fwrd.count_fwd is null) then 0 else fwrd.count_fwd end)) desc) as rnk
from bkwd
left outer join fwrd on fwrd.fwd = bkwd.bkw
order by ttl desc)
select *,
rank () OVER(ORDER BY total_points desc) type1_rank
from pkmn
where concat(type_2,',',type_1) = (select rnk.grp from rnk where rnk = 1)
Top 15 Results:
| pokedex_number | name | type_1 | type_2 | total_points | type1_rank |
|---|---|---|---|---|---|
| 382 | Primal Kyogre | Water | None | 770 | 1 |
| 382 | Kyogre | Water | None | 670 | 2 |
| 9 | Mega Blastoise | Water | None | 630 | 3 |
| 746 | Wishiwashi School Form | Water | None | 620 | 4 |
| 490 | Manaphy | Water | None | 600 | 5 |
| 245 | Suicune | Water | None | 580 | 6 |
| 350 | Milotic | Water | None | 540 | 7 |
| 818 | Inteleon | Water | None | 530 | 8 |
| 160 | Feraligatr | Water | None | 530 | 8 |
| 9 | Blastoise | Water | None | 530 | 8 |
| 503 | Samurott | Water | None | 528 | 11 |
| 134 | Vaporeon | Water | None | 525 | 12 |
| 693 | Clawitzer | Water | None | 500 | 13 |
| 55 | Golduck | Water | None | 500 | 13 |
| 321 | Wailord | Water | None | 500 | 13 |