| |
| |
| |
| |
|
|
| |
| CREATE TABLE IF NOT EXISTS clutch_stats ( |
| season TEXT NOT NULL, |
| player_id INTEGER NOT NULL, |
| player_name TEXT, |
| team_abbreviation TEXT, |
| gp INTEGER, w INTEGER, l INTEGER, min NUMERIC, |
| fgm NUMERIC, fga NUMERIC, fg_pct NUMERIC, |
| fg3m NUMERIC, fg3a NUMERIC, fg3_pct NUMERIC, |
| ftm NUMERIC, fta NUMERIC, ft_pct NUMERIC, |
| reb NUMERIC, ast NUMERIC, tov NUMERIC, stl NUMERIC, blk NUMERIC, |
| pts NUMERIC, plus_minus NUMERIC, |
| dd2 INTEGER, td3 INTEGER, |
| PRIMARY KEY (season, player_id) |
| ); |
|
|
| |
| |
| |
| |
| |
| CREATE OR REPLACE VIEW v_clutch AS |
| SELECT |
| season, player_id, player_name, team_abbreviation, |
| gp, w, l, min, |
| fgm, fga, fg_pct, fg3m, fg3a, fg3_pct, ftm, fta, ft_pct, |
| reb, ast, tov, stl, blk, pts, plus_minus, dd2, td3, |
| round(pts / nullif(2 * (fga + 0.44 * fta), 0), 3) AS ts_pct, |
| round((fgm + 0.5 * fg3m) / nullif(fga, 0), 3) AS efg_pct, |
| round(pts / nullif(min, 0), 2) AS pts_per_min |
| FROM clutch_stats; |
|
|
| |
| CREATE TABLE IF NOT EXISTS hustle_stats ( |
| season TEXT NOT NULL, |
| player_id INTEGER NOT NULL, |
| player_name TEXT, |
| team_abbreviation TEXT, |
| g INTEGER, min NUMERIC, |
| contested_shots NUMERIC, |
| contested_shots_2pt NUMERIC, |
| contested_shots_3pt NUMERIC, |
| deflections NUMERIC, |
| charges_drawn NUMERIC, |
| screen_assists NUMERIC, |
| screen_ast_pts NUMERIC, |
| loose_balls_recovered NUMERIC, |
| box_outs NUMERIC, |
| PRIMARY KEY (season, player_id) |
| ); |
|
|
| |
| CREATE TABLE IF NOT EXISTS defense_tracking ( |
| season TEXT NOT NULL, |
| player_id INTEGER NOT NULL, |
| player_name TEXT, |
| player_position TEXT, |
| gp INTEGER, |
| freq NUMERIC, |
| d_fgm NUMERIC, d_fga NUMERIC, d_fg_pct NUMERIC, |
| normal_fg_pct NUMERIC, |
| pct_plusminus NUMERIC, |
| PRIMARY KEY (season, player_id) |
| ); |
|
|
| |
| |
| |
| |
| |
| |
| DROP MATERIALIZED VIEW IF EXISTS player_advanced; |
| CREATE MATERIALIZED VIEW player_advanced AS |
| SELECT |
| player_id, |
| max(player_name) AS player_name, |
| season, |
| count(*) AS gp, |
| sum(min) AS min, |
| round(sum(pts) / nullif(2 * (sum(fga) + 0.44 * sum(fta)), 0)::numeric, 3) AS ts_pct, |
| round((sum(fgm) + 0.5 * sum(fg3m)) / nullif(sum(fga), 0)::numeric, 3) AS efg_pct, |
| round(sum(fg3a)::numeric / nullif(sum(fga), 0), 3) AS fg3a_rate, |
| round(sum(fta)::numeric / nullif(sum(fga), 0), 3) AS ft_rate, |
| round(sum(ast)::numeric / nullif(sum(tov), 0), 2) AS ast_to, |
| round(36 * sum(pts)::numeric / nullif(sum(min), 0), 1) AS pts_per36, |
| round(36 * sum(reb)::numeric / nullif(sum(min), 0), 1) AS reb_per36, |
| round(36 * sum(ast)::numeric / nullif(sum(min), 0), 1) AS ast_per36, |
| round(sum(pts) / nullif(sum(fga) + 0.44 * sum(fta), 0)::numeric, 2) AS pts_per_shot |
| FROM player_game_logs |
| WHERE season_type = 'Regular Season' |
| GROUP BY player_id, season; |
| CREATE UNIQUE INDEX IF NOT EXISTS idx_player_advanced ON player_advanced (player_id, season); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| CREATE OR REPLACE VIEW player_improvement AS |
| SELECT |
| a.player_id, a.player_name, a.season, |
| a.gp, b.gp AS prev_gp, |
| a.ts_pct, b.ts_pct AS prev_ts_pct, round(a.ts_pct - b.ts_pct, 3) AS ts_pct_delta, |
| a.efg_pct, b.efg_pct AS prev_efg_pct, round(a.efg_pct - b.efg_pct, 3) AS efg_pct_delta, |
| a.pts_per36, b.pts_per36 AS prev_pts_per36, round(a.pts_per36 - b.pts_per36, 1) AS pts_per36_delta, |
| a.reb_per36, b.reb_per36 AS prev_reb_per36, round(a.reb_per36 - b.reb_per36, 1) AS reb_per36_delta, |
| a.ast_per36, b.ast_per36 AS prev_ast_per36, round(a.ast_per36 - b.ast_per36, 1) AS ast_per36_delta |
| FROM player_advanced a |
| JOIN player_advanced b |
| ON b.player_id = a.player_id |
| AND b.season = (left(a.season, 4)::int - 1)::text || '-' |
| || lpad((left(a.season, 4)::int % 100)::text, 2, '0') |
| WHERE a.gp >= 20 AND b.gp >= 20; |
|
|
| |
| |
| |
| |
| DROP MATERIALIZED VIEW IF EXISTS team_advanced; |
| CREATE MATERIALIZED VIEW team_advanced AS |
| WITH g AS ( |
| SELECT tm.abbreviation AS team, t.season, |
| (t.wl = 'W')::int AS win, |
| t.pts, opp.pts AS opp_pts, |
| t.fga, t.fta, t.tov, t.oreb, t.fgm, t.fg3m, |
| opp.fga AS o_fga, opp.fta AS o_fta, opp.tov AS o_tov, |
| opp.oreb AS o_oreb, opp.dreb AS o_dreb, t.dreb AS dreb |
| FROM team_game_logs t |
| JOIN teams tm ON tm.team_id = t.team_id |
| LEFT JOIN team_game_logs opp |
| ON opp.game_id = t.game_id AND opp.team_id <> t.team_id |
| WHERE t.season_type = 'Regular Season' |
| ) |
| SELECT |
| team, season, count(*) AS gp, sum(win) AS wins, |
| round(100 * sum(pts) / nullif(sum(fga + 0.44 * fta + tov - oreb), 0)::numeric, 1) AS off_rtg, |
| round(100 * sum(opp_pts) / nullif(sum(o_fga + 0.44 * o_fta + o_tov - o_oreb), 0)::numeric, 1) AS def_rtg, |
| round(100 * sum(pts) / nullif(sum(fga + 0.44 * fta + tov - oreb), 0)::numeric |
| - 100 * sum(opp_pts) / nullif(sum(o_fga + 0.44 * o_fta + o_tov - o_oreb), 0)::numeric, 1) AS net_rtg, |
| round(sum(fga + 0.44 * fta + tov - oreb)::numeric / nullif(count(*), 0), 1) AS pace, |
| round((sum(fgm) + 0.5 * sum(fg3m)) / nullif(sum(fga), 0)::numeric, 3) AS efg_pct, |
| round(sum(tov) / nullif(sum(fga + 0.44 * fta + tov - oreb), 0)::numeric, 3) AS tov_rate, |
| round(sum(oreb)::numeric / nullif(sum(oreb + o_dreb), 0), 3) AS oreb_rate, |
| round(sum(fta)::numeric / nullif(sum(fga), 0), 3) AS ft_rate |
| FROM g |
| GROUP BY team, season; |
| CREATE UNIQUE INDEX IF NOT EXISTS idx_team_advanced ON team_advanced (team, season); |
|
|
| |
| |
| CREATE OR REPLACE VIEW v_team_season AS |
| SELECT |
| tm.abbreviation AS team, |
| t.season, |
| count(*) AS gp, |
| sum((t.wl = 'W')::int) AS wins, |
| sum((t.wl = 'L')::int) AS losses, |
| round(avg(t.pts), 1) AS pts_pg, |
| round(avg(opp.pts), 1) AS opp_pts_pg, |
| round(avg(t.pts) - avg(opp.pts), 1) AS net_pg, |
| round(avg(t.fg3a), 1) AS fg3a_pg, |
| round(sum(t.fg3m)::numeric / nullif(sum(t.fg3a), 0), 3) AS fg3_pct |
| FROM team_game_logs t |
| JOIN teams tm ON tm.team_id = t.team_id |
| LEFT JOIN team_game_logs opp |
| ON opp.game_id = t.game_id AND opp.team_id <> t.team_id |
| WHERE t.season_type = 'Regular Season' |
| GROUP BY tm.abbreviation, t.season; |
|
|