Query a database table
Summarize 2013’s hourly weather at the three New York City airports in an SQLite table, with phibble’s methods compiled to one SQL query that the database runs. The table holds nycflights13’s weather data from the PHPstats datasets: the script reads the CSV and loads five columns into an in-memory SQLite database before the code shown. It needs the pdo_sqlite extension.
use Phibble\Sql\SqlTable;use function Phibble\tbl;use function Phibble\Expr\{col, desc, max, mean, n, sum};$weather = tbl($pdo, 'weather');$airports = $weather |> (fn (SqlTable $t) => $t->filter(col('temp')->isNa()->not())) |> (fn (SqlTable $t) => $t->groupBy(['origin'])) |> (fn (SqlTable $t) => $t->summarize([ 'hours' => n(), 'temp' => mean(col('temp')), 'precip' => sum(col('precip')), 'gust' => max(col('wind_gust'), na_rm: true), ])) |> (fn (SqlTable $t) => $t->arrange([desc(col('precip'))]));echo $airports->showQuery(), "\n\n";echo $airports->collect(), "\n";use function Phibble\tbl;use function Phibble\Expr\{col, desc, max, mean, n, sum};$weather = tbl($pdo, 'weather');$airports = $weather ->filter(col('temp')->isNa()->not()) ->groupBy(['origin']) ->summarize([ 'hours' => n(), 'temp' => mean(col('temp')), 'precip' => sum(col('precip')), 'gust' => max(col('wind_gust'), na_rm: true), ]) ->arrange([desc(col('precip'))]);echo $airports->showQuery(), "\n\n";echo $airports->collect(), "\n";
The SQL from showQuery()
SELECT "origin", "hours", "temp", "precip", "gust" FROM (SELECT "origin", "hours", "temp", "precip", "gust", ROW_NUMBER() OVER (ORDER BY ("origin" IS NULL), "origin") AS "__phibble_row" FROM (SELECT "origin" AS "origin", COUNT(*) AS "hours", (CASE WHEN COUNT(*) > COUNT("temp") THEN NULL ELSE (CASE WHEN COUNT("temp") = 0 THEN NULL ELSE AVG(CAST("temp" AS REAL)) END) END) AS "temp", (CASE WHEN COUNT(*) > COUNT("precip") THEN NULL ELSE COALESCE(SUM("precip"), 0) END) AS "precip", (CASE WHEN COUNT("wind_gust") = 0 THEN -9e999 ELSE MAX("wind_gust") END) AS "gust" FROM (SELECT * FROM (SELECT *, rowid AS "__phibble_row" FROM "weather") AS q1 WHERE (NOT ("temp" IS NULL))) AS q2 GROUP BY "origin") AS q3) AS q4 ORDER BY ("precip" IS NULL), "precip" DESC, ("__phibble_row" IS NULL), "__phibble_row"
# A tibble: 3 × 5
origin hours temp precip gust
<chr> <int> <dbl> <dbl> <dbl>
1 EWR 8702 55.5 43.8 58.7
2 LGA 8706 55.8 38.1 62.1
3 JFK 8706 54.5 34.7 66.7
- Each airport has about 8,700 hourly readings with a temperature.
- Newark (EWR) had the most precipitation, 43.8 inches over the year, and JFK the least, 34.7 inches. Mean temperatures differ by about 1 °F, and JFK had the strongest gust, 66.7 mph.
max(..., na_rm: true)skips the hours without a gust;mean()andsum()need nona_rmhere, because the filter keeps only hours with a temperature and every such hour has a precipitation value.- Table methods only build the query. Nothing runs on the database until
collect()returns aDataFrame.showQuery()shows the SQL with?placeholders. - The same code runs on PostgreSQL and MySQL.
Runnable scripts: PHP 8.5+ · PHP 8.3–8.4.
Reference: SQL tables · phplyr.