关于 query
使用 DuckDB 查询文件或已保存会话数据的 skill。它可将自然语言请求转为 SQL、执行前估算结果规模、运行查询并解读结果。
主要功能
- 01判断会话模式或临时模式
- 02将自然语言转换为 SQL
- 03执行前估算结果规模
- 04沙箱化执行文件查询
- 05解读结果并处理错误
适用场景
- 01查询 CSV 或 Parquet 文件
- 02检查已保存会话中的表
- 03用自然语言问题获取 SQL 查询结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ duckdb/ duckdb-skills --skill query安装后在 Claude Code 中输入/query确认已加载。
详细介绍
你正在帮助用户使用 DuckDB 查询数据。
输入:$@
请按顺序执行以下步骤。
步骤 1 — 解析状态并确定模式
在以下任一位置查找现有状态文件:
STATE_DIR=""
test -f .duckdb-skills/state.sql && STATE_DIR=".duckdb-skills"
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")"
PROJECT_ID="$(echo "$PROJECT_ROOT" | tr '/' '-')"
test -f "$HOME/.duckdb-skills/$PROJECT_ID/state.sql" && STATE_DIR="$HOME/.duckdb-skills/$PROJECT_ID"
如果找到,请确认它引用的数据库仍可访问:
duckdb -init "$STATE_DIR/state.sql" -c "SHOW DATABASES;"
现在确定模式:
- 临时查询模式:存在
--file标志,或 SQL 引用了文件路径/字面值(例如FROM 'data.csv'),或STATE_DIR为空。 - 会话模式:已设置
STATE_DIR,且输入引用了表名、使用自然语言,或是未引用文件的 SQL。
如果不存在状态文件,且未引用文件,则回退到针对 :memory: 的临时查询模式——用户必须在 SQL 中直接引用文件。
如果状态文件存在,但其中任意 ATTACH 失败,则提醒用户并回退到临时查询模式。
步骤 2 — 检查是否已安装 DuckDB
command -v duckdb
如果未找到,则委托给 /duckdb-skills:install-duckdb,然后继续。
步骤 3 — 按需生成 SQL
如果输入是自然语言(而非有效 SQL),请使用下方的 Friendly SQL 参考生成 SQL。
在会话模式下,先获取架构信息,以便生成查询:
duckdb -init "$STATE_DIR/state.sql" -csv -c "
SELECT table_name FROM duckdb_tables() ORDER BY table_name;
"
然后针对相关表:
duckdb -init "$STATE_DIR/state.sql" -csv -c "DESCRIBE <table_name>;"
使用架构上下文和 Friendly SQL 参考生成最合适的查询。
步骤 4 — 估算结果大小
执行前,估算查询是否可能产生非常大的结果,从而在返回到此对话时消耗过多令牌。
会话模式 — 检查相关表的行数:
duckdb -init "$STATE_DIR/state.sql" -csv -c "
SELECT table_name, estimated_size, column_count
FROM duckdb_tables()
WHERE table_name IN ('<table1>', '<table2>');
"
临时查询模式 — 探查数据源:
duckdb :memory: -csv -c "
SET allowed_paths=['FILE_PATH'];
SET enable_external_access=false;
SET allow_persistent_secrets=false;
SET lock_configuration=true;
SELECT count() AS row_count FROM 'FILE_PATH';
"
评估:
- 如果查询已有
LIMIT、count()或其他可限制输出的聚合操作 -> 安全,可以继续。 - 如果数据源有超过 1M 行,且查询没有 LIMIT 或聚合操作 -> 告知用户:
“此查询会返回非常庞大的结果集。在此处显示会消耗大量令牌并增加成本。建议添加
LIMIT 1000或聚合操作,以控制输出规模。” 运行原查询前请征求用户确认。 - 如果数据大小超过 10 GB -> 还需提醒: “此表超过 10 GB,查询可能需要一些时间才能完成。” 用户确认后继续。
对于结果范围天然受限的查询(例如 DESCRIBE、SUMMARIZE、聚合操作、count()),跳过此步骤。
步骤 5 — 执行查询
临时查询模式(在沙盒中运行——仅可访问被引用的文件):
duckdb :memory: -csv <<'SQL'
SET allowed_paths=['FILE_PATH'];
SET enable_external_access=false;
SET allow_persistent_secrets=false;
SET lock_configuration=true;
<QUERY>;
SQL
将 FILE_PATH 替换为从查询或 --file 参数中提取的实际文件路径。
如果引用了多个文件,请将所有路径都包含在 allowed_paths 列表中。
会话模式(用户信任的数据库):
duckdb -init "$STATE_DIR/state.sql" -csv -c "<QUERY>"
对于多行查询,使用带 -init 的 heredoc:
duckdb -init "$STATE_DIR/state.sql" -csv <<'SQL'
<QUERY>;
SQL
多行查询始终使用 heredoc(<<'SQL'),以避免 shell 引号问题。
步骤 6 — 处理错误
- 语法错误:显示错误,建议修正后的查询,然后重新运行。
- 缺少扩展(例如
Extension "X" not loaded):委托给/duckdb-skills:install-duckdb <ext>,然后重试。 - 未找到表(会话模式):使用
FROM duckdb_tables()列出可用表,并建议修正名称。 - 未找到文件(临时查询模式):使用
find "$PWD" -name "<filename>" 2>/dev/null定位文件,并建议修正后的路径。 - 持续出现或含义不明的 DuckDB 错误:使用
/duckdb-skills:duckdb-docs <error message or relevant keywords>搜索文档获取指导,然后应用修复并重试。
步骤 7 — 展示结果
向用户展示查询输出。如果结果超过 100 行,请说明结果已截断,并建议在查询中添加 LIMIT。
对于自然语言问题,还需简要解读结果。
DuckDB Friendly SQL 参考
生成 SQL 时,优先使用以下符合 DuckDB 惯例的构造:
紧凑子句
- FROM 优先:
FROM table WHERE x > 10(隐式使用SELECT *) - GROUP BY ALL:自动按所有非聚合列分组
- ORDER BY ALL:按所有列排序,以确保结果确定
- SELECT * EXCLUDE (col1, col2):从通配符中排除列
- SELECT * REPLACE (expr AS col):就地转换列
- UNION ALL BY NAME:合并列顺序不同的表
- 百分比 LIMIT:
LIMIT 10%返回一定百分比的行 - 前缀别名:使用
SELECT x: 42,而非SELECT 42 AS x - SELECT 列表允许尾随逗号
查询功能
- count():无需使用
count(*) - 可复用别名:在 WHERE / GROUP BY / HAVING 中使用列别名
- 横向列别名:
SELECT i+1 AS j, j+2 AS k - COLUMNS(*):对多列应用表达式;支持正则表达式、EXCLUDE、REPLACE 和 lambda
- FILTER 子句:使用
count() FILTER (WHERE x > 10)进行条件聚合 - GROUPING SETS / CUBE / ROLLUP:高级多级聚合
- 每组 Top-N:
max(col, 3)以列表形式返回前 3 项;也可使用arg_max(arg, val, n)、min_by(arg, val, n) - DESCRIBE table_name:架构摘要(列名和类型)
- SUMMARIZE table_name:即时生成统计概览
- PIVOT / UNPIVOT:在宽格式和长格式之间重塑数据
- SET VARIABLE x = expr:定义 SQL 级变量,并使用
getvariable('x')引用
数据导入
- 直接查询文件:
FROM 'file.csv'、FROM 'data.parquet' - 通配符匹配:
FROM 'data/part-*.parquet'可读取多个文件 - 自动检测:自动推断 CSV 标头和架构
表达式和类型
- 点运算符链式调用:
'hello'.upper()或col.trim().lower() - 列表推导式:
[x*2 FOR x IN list_col] - 列表/字符串切片:
col[1:3]、负索引col[-1] - STRUCT. 表示法*:
SELECT s.* FROM (SELECT {'a': 1, 'b': 2} AS s) - 方括号列表:
[1, 2, 3] - format():使用
format('{}->{}', a, b)格式化字符串
连接
- ASOF 连接:对有序数据(例如时间戳)进行近似匹配
- POSITIONAL 连接:按位置而非键匹配行
- LATERAL 连接:在子查询中引用之前的表表达式
数据修改
- CREATE OR REPLACE TABLE:无需先执行
DROP TABLE IF EXISTS - CREATE TABLE ... AS SELECT (CTAS):根据查询结果创建表
- INSERT INTO ... BY NAME:按列名而非位置匹配列
- INSERT OR IGNORE INTO / INSERT OR REPLACE INTO:实现 upsert 模式