如何在命令行对CSV文件内容执行SQL查询?
针对CSV文件执行复杂SQL查询的轻量方案
在Linux命令行下,完全可以不用完整的DBMS服务,用以下几种低开销的方式实现需求:
1. 用SQLite内存数据库(最推荐)
SQLite是无服务的嵌入式数据库,支持子查询、自连接、窗口函数(3.25.0及以上版本),可以直接在内存中创建临时库,导入CSV后执行查询,结束后无任何残留文件。
命令行直接执行
假设你的CSV文件是data.csv,表头为第一行,执行复杂查询的命令如下:
sqlite3 :memory: <<'EOF' .mode csv .import data.csv my_table -- 这里写你的复杂查询,比如带窗口函数和子查询的例子 SELECT user_id, order_amount, RANK() OVER (PARTITION BY user_id ORDER BY order_date DESC) AS order_rank, (SELECT COUNT(*) FROM my_table WHERE user_id = t.user_id) AS total_orders FROM my_table t WHERE order_amount > (SELECT AVG(order_amount) FROM my_table) EOF
- 用
:memory:指定内存数据库,不会生成磁盘文件 .mode csv设置导入模式为CSV,.import自动将表头作为列名- 支持所有SQLite兼容的复杂语法,性能足够处理小体积CSV
如果CSV没有表头,可以手动指定列名:
sqlite3 :memory: <<'EOF' .mode csv CREATE TABLE my_table (col1 TEXT, col2 INTEGER, col3 REAL); .import --skip 1 data.csv my_table -- 执行查询 SELECT * FROM my_table; EOF
2. Python脚本(适合需要后续处理结果的场景)
用Python结合pandas和sqlite3,可以快速将CSV导入内存数据库,执行复杂查询后还能方便地处理输出结果。
示例脚本query_csv.py:
import sqlite3 import pandas as pd # 读取CSV(根据实际情况调整参数,比如encoding、sep等) df = pd.read_csv('data.csv', encoding='utf-8') # 连接内存SQLite数据库 conn = sqlite3.connect(':memory:') # 将DataFrame写入临时表,index=False避免生成额外索引列 df.to_sql('temp_table', conn, index=False) # 编写你的复杂SQL查询 sql_query = """ SELECT category, product_name, SUM(sales) AS total_sales, RATIO_TO_REPORT(SUM(sales)) OVER (PARTITION BY category) AS sales_ratio FROM temp_table GROUP BY category, product_name HAVING total_sales > (SELECT AVG(total_sales) FROM ( SELECT SUM(sales) AS total_sales FROM temp_table GROUP BY product_name )) """ # 执行查询并获取结果 result_df = pd.read_sql(sql_query, conn) # 输出结果,可以是CSV格式或直接打印 print(result_df.to_csv(index=False)) # 如果要保存结果到文件: # result_df.to_csv('query_result.csv', index=False)
运行脚本:
python3 query_csv.py
- 灵活性高,可集成到自动化工作流中
- 支持所有SQLite的SQL特性,处理结果方便
3. csvkit工具(简化命令行操作)
csvkit是一套处理CSV的命令行工具,其中csvsql可以直接对CSV执行SQL查询,底层依赖SQLite,语法支持度和SQLite一致。
先安装csvkit(如果没安装的话):
sudo apt install csvkit # Debian/Ubuntu # 或用pip安装 pip install csvkit
执行查询的命令:
csvsql --query "SELECT user_id, MAX(order_amount) FROM data.csv GROUP BY user_id" data.csv
如果要执行复杂查询,可以把SQL写到文件里:
csvsql --query @query.sql data.csv
其中query.sql是你的复杂查询脚本。
- 命令更简洁,但对于极复杂的窗口函数,建议先确认SQLite版本兼容性
内容的提问来源于stack exchange,提问作者einpoklum
相关产品推荐
相关产品推荐

