10 个版本
0.0.15 | 2023 年 3 月 27 日 |
---|---|
0.0.14 | 2022 年 11 月 9 日 |
0.0.12 | 2022 年 10 月 24 日 |
#661 在 数据库接口
每月 37 次下载
1MB
520 行
prql-query (pq)
使用 PRQL 查询和转换数据
PRQL 是一种用于转换数据的现代语言——一个简单、强大的管道式 SQL 替代品
pq
允许您使用 PRQL 轻松查询和转换您的数据。它由 Apache Arrow DataFusion 和 DuckDB 提供支持,并使用 Rust 编写(因此它“非常快”™)!
示例
$ pq --from albums.csv "take 5"
+----------+---------------------------------------+-----------+
| album_id | title | artist_id |
+----------+---------------------------------------+-----------+
| 1 | For Those About To Rock We Salute You | 1 |
| 2 | Balls to the Wall | 2 |
| 3 | Restless and Wild | 2 |
| 4 | Let There Be Rock | 1 |
| 5 | Big Ones | 3 |
+----------+---------------------------------------+-----------+
$ pq -f i=invoices.csv -f c=customers.csv --to invoices_with_names.parquet \
'from i | join c [customer_id] | derive [name = f"{first_name} {last_name}"]'
$ pq -f invoices_with_names.parquet --format json \
'group name (aggregate [spend = sum total]) | sort [-spend] | take 10'
{"name":"Helena Holý","spend":49.620000000000005}
{"name":"Richard Cunningham","spend":47.620000000000005}
{"name":"Luis Rojas","spend":46.62}
{"name":"Hugh O'Reilly","spend":45.62}
{"name":"Ladislav Kovács","spend":45.62}
{"name":"Julia Barnett","spend":43.620000000000005}
{"name":"Fynn Zimmermann","spend":43.62}
{"name":"Frank Ralston","spend":43.62}
{"name":"Astrid Gruber","spend":42.62}
{"name":"Victor Stevens","spend":42.62}
安装
从 Github 发布版下载二进制文件
每个发布版都会为 Windows、macOS 和 Linux 构建二进制文件,可以从 发布版 (最新版) 下载。
例如,在 Linux 上,您可以使用以下命令下载和安装 pq
VERSION=v0.0.14 wget https://github.com/prql/prql-query/releases/download/$VERSION/pq-x86_64-unknown-linux-gnu.tar.gz && \
tar xvzf pq-x86_64-unknown-linux-gnu.tar.gz --directory ~/.local/bin && \
rm pq-x86_64-unknown-linux-gnu.tar.gz
作为容器镜像运行 (Docker)
docker pull ghcr.io/prql/prql-query
alias pq="docker run --rm -it -v $(pwd):/data -e HOME=/tmp -u $(id -u):$(id -g) ghcr.io/prql/prql-query"
pq --help
请注意,如果您想使用 Docker 自己构建容器镜像,那么 Docker VM 至少需要 10 GB 的内存,否则 libduckdb-sys 将无法编译。
通过 Homebrew
brew tap prql/homebrew-prql-query
brew install prql-query
通过 Rust 工具链 (Cargo)
cargo install prql-query
用法
生成 SQL
在 simplest 中,pq
将 PRQL 查询转换为 SQL 查询
$ pq "from a | select b"
SELECT
b
FROM
a
输入也可以来自 stdin
$ cat examples/queries/invoice_totals.prql | pq
为了方便,以 ".prql" 结尾的查询假定是 PRQL 查询文件的路径,并将被读取,因此这会产生与上面相同的结果
$ pq examples/queries/invoice_totals.prql
这两个都会产生以下输出
SELECT
STRFTIME('%Y-%m', i.invoice_date) AS month,
STRFTIME('%Y-%m-%d', i.invoice_date) AS day,
COUNT(DISTINCT i.invoice_id) AS num_orders,
SUM(ii.quantity) AS num_tracks,
SUM(ii.unit_price * ii.quantity) AS total_price,
SUM(SUM(ii.quantity)) OVER (
PARTITION BY STRFTIME('%Y-%m', i.invoice_date)
ORDER BY
STRFTIME('%Y-%m-%d', i.invoice_date) ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW
) AS running_total_num_tracks,
LAG(SUM(ii.quantity), 7) OVER (
ORDER BY
STRFTIME('%Y-%m-%d', i.invoice_date) ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
) AS num_tracks_last_week
FROM
invoices AS i
JOIN invoice_items AS ii USING(invoice_id)
GROUP BY
STRFTIME('%Y-%m', i.invoice_date),
STRFTIME('%Y-%m-%d', i.invoice_date)
ORDER BY
day
从数据库查询数据(使用 CLI 客户端)
通过上述功能,您应该能够使用您最喜欢的 CLI 客户端和 pq
查询您最喜欢的 SQL RDBMS。例如,使用 PostgreSQL 的 psql
客户端
$ pq "from my_table | take 5" | psql postgresql://username:password@host:port/database
或者使用存储在文件中的 PRQL 查询的 MySQL 的 mysql
客户端
$ pq my_query.prql | mysql -h myhost -d mydb -u myuser -p mypassword
同样适用于 MS SQL Server 和其他数据库。
查询文件中的数据(csv、parquet、json)
对于查询和转换本地文件系统上存储的数据,pq
提供了多个内置的后端查询处理引擎。默认后端是 Apache Arrow DataFusion。然而,也支持 DuckDB 和 SQLite(计划中)。
当提供 --from
参数指定数据文件时,PRQL 查询将被应用于这些文件。可以在查询中通过文件名(不带扩展名)引用文件,例如,customers.csv 可以作为表 customers
引用。为了方便起见,除非查询已经以 from ...
步骤开始,否则将在查询的开始处自动插入一个 from <table>
管道步骤,引用最后遇到的 --from
参数,即以下两个是等效的
$ pq --from examples/data/chinook/csv/invoices.csv "from invoices|take 5"
$ pq --from examples/data/chinook/csv/invoices.csv "take 5"
+------------+-------------+-------------------------------+-------------------------+--------------+---------------+-----------------+---------------------+-------+
| invoice_id | customer_id | invoice_date | billing_address | billing_city | billing_state | billing_country | billing_postal_code | total |
+------------+-------------+-------------------------------+-------------------------+--------------+---------------+-----------------+---------------------+-------+
| 1 | 2 | 2009-01-01T00:00:00.000000000 | Theodor-Heuss-Straße 34 | Stuttgart | | Germany | 70174 | 1.98 |
| 2 | 4 | 2009-01-02T00:00:00.000000000 | Ullevålsveien 14 | Oslo | | Norway | 0171 | 3.96 |
| 3 | 8 | 2009-01-03T00:00:00.000000000 | Grétrystraat 63 | Brussels | | Belgium | 1000 | 5.94 |
| 4 | 14 | 2009-01-06T00:00:00.000000000 | 8210 111 ST NW | Edmonton | AB | Canada | T6G 2C7 | 8.91 |
| 5 | 23 | 2009-01-11T00:00:00.000000000 | 69 Salem Street | Boston | MA | USA | 2113 | 13.86 |
+------------+-------------+-------------------------------+-------------------------+--------------+---------------+-----------------+---------------------+-------+
您还可以使用以下形式为源文件分配别名:--from <alias>=<filepath>
然后在查询中通过该别名引用它。所以以下也是上述查询的另一种等效形式
$ pq --from i=examples/data/chinook/csv/invoices.csv "from i|take 5"
这适用于多个文件,这意味着上述扩展示例可以按以下方式运行
$ pq -b duckdb -f examples/data/chinook/csv/invoices.csv -f examples/data/chinook/csv/invoice_items.csv examples/queries/invoice_totals.prql
使用 pq
转换数据并将输出写入文件
当提供 --to
参数时,输出将被写入那里,而不是 stdout(空查询等价于 select *
,并且是必需的,因为目前 select *
不可用)
$ pq --from examples/data/chinook/csv/invoices.csv --to invoices.parquet ""
目前,支持 csv、parquet 和 json 文件格式,既适用于读取器也适用于写入器
$ cat examples/queries/customer_totals.prql
group [customer_id] (
aggregate [
customer_total = sum total,
])
$ pq -f invoices.parquet -t customer_totals.json examples/queries/customer_totals.prql
$ pq -f customer_totals.json "sort [-customer_total] | take 10"
+-------------+--------------------+
| customer_id | customer_total |
+-------------+--------------------+
| 6 | 49.620000000000005 |
| 26 | 47.620000000000005 |
| 57 | 46.62 |
| 46 | 45.62 |
| 45 | 45.62 |
| 28 | 43.620000000000005 |
| 37 | 43.62 |
| 24 | 43.62 |
| 7 | 42.62 |
| 25 | 42.62 |
+-------------+--------------------+
查询 DuckDB 数据库中的数据
DuckDB 原生支持,可以通过以 "duckdb://" 开头的数据库 URI 进行查询。
$ pq --database duckdb://examples/chinook/duckdb/chinook.duckdb \
'from albums | join artists [artist_id] | group name (aggregate [num_albums = count]) | sort [-num_albums] | take 10'
查询 Sqlite 数据库
Sqlite 目前通过 DuckDB 扩展 sqlite_scanner 支持。为了查询 Sqlite 数据库,需要提供以 "sqlite://" 开头的数据库 URI。
$ pq --database sqlite://examples/chinook/sqlite/chinook.sqlite \
'from albums | take 10'
查询 PostgreSQL 数据库
PostgreSQL 目前通过 DuckDB 扩展 postgres-scanner 支持。(请参阅 公告博客文章 以获取良好的介绍。)
$ pq -d postgresql://username:password@host:port/database \
'from table | take 10'
此方法的一个值得注意的局限性是,您只能查询 postgres 数据库中的表,而不能查询视图。
默认情况下,您将连接到 "public" 模式,可以在查询中引用该模式中的表。您可以使用 "?currentSchema=schema" 参数指定要连接的不同模式。如果您想查询该模式之外的另一个模式中的表,您目前必须像这样通过别名 --from
参数引用它们
$ pq -d postgresql://username:password@host:port/database?currentSchema=schema \
--from alias=other_schema.table 'from alias | take 10'
环境变量
如果您计划反复使用同一数据库,那么每次都指定详细信息很快就变得繁琐。 pq
允许您使用带 PQ_
前缀的环境变量提供所有命令行参数。例如,上述相同的查询可以通过以下方式实现
$ export PQ_DATABASE="postgresql://username:password@host:port/database"
$ pq --from alias=schema.table 'take 10'
.env 文件
环境变量也可以从.env
文件中读取。由于你可能不希望将数据库凭据暴露在shell中,因此将其放入.env
文件中是有意义的。这还允许你将配置目录与环境的常见查询一起设置,例如
$ echo 'PQ_DATABASE="postgresql://username:password@host:port/database"' > .env
$ pq 'from my_schema.my_table | take 5'
或者,比如说你有一个需要在多个环境上运行的status_query.prql
,这些环境已经设置了子目录中的.env文件
$ for e in prod uat dev; do cd $e && pq ../status_query.prql; done
路线图
0.1.0
- 测试
- 发布到crates.io
0.2.0
- 支持对象存储
0.3.0
- 通过
connectorx
支持其他数据库
依赖关系
~74MB
~1.5M SLoC