用 Shaper 10 分钟搭建 SQL 仪表盘:DuckDB 的开源可视化利器

还在为可视化工具发愁?Shaper 是一款完全开源、SQL 驱动的仪表盘工具,底层由 DuckDB 驱动。只需要写 SQL,10 分钟就能搭建出专业的交互式数据仪表盘。本文带你从零开始实战。

一、痛点:数据可视化好烦

你有数据,但你有仪表盘吗?

这是每个数据分析师都会遇到的尴尬:数据已经整整齐齐躺在 DuckDB 里了,但老板要看可视化仪表盘。你打开 Tableau → 太贵。打开 Metabase → 太重。写 Python + Plotly → 代码量太大为了一个小报表不值当。

要不,直接用 SQL 画仪表盘?

Shaper 就是干这个的——一款完全开源SQL 驱动的仪表盘工具,底层由 DuckDB 提供查询引擎。你只需要写 SQL,它自动把查询结果渲染成柱状图、折线图、饼图、表格……

项目地址:https://github.com/taleshape-com/shaper(1.1k ⭐,持续活跃)


二、Shaper 是什么?

Shaper 的定位非常清晰:面向 SQL 用户的 DuckDB 可视化层

用官方的话说:“All in SQL, Powered by DuckDB。”

它的核心理念是:你不需要学任何新的 API 或 DSL。你只需要在 SQL 查询的末尾加上 ::BARCHART::XAXIS 之类的类型标注,Shaper 就知道该怎么画图。

-- Shaper 的 SQL 范例
SELECT
  date_trunc('week', created_at)::XAXIS,
  category::CATEGORY,
  count()::BARCHART_STACKED
FROM dataset
GROUP BY ALL ORDER BY ALL;

这段 SQL 返回的就是一张堆叠柱状图——没有 JavaScript、没有 JSON 配置、没有拖拽操作。

核心特性一览

能力说明
完全开源MPL-2.0 协议,可自托管
SQL 优先用 SQL 类型标注定义图表
Git 工作流仪表盘版本化管理
多数据源同一查询跨多个数据源
白标嵌入支持 iframe 和无 iframe 嵌入
导出PDF、PNG、CSV、Excel 一键导出
定时报告自动生成并发送报告
行级安全JWT token 控制数据权限

三、10 分钟快速上手

第 1 分钟:启动 Shaper

最简单的方式是用 Docker(如果你有 Docker 环境的话):

docker run --rm -it -p5454:5454 taleshape/shaper

打开浏览器访问 http://localhost:5454——一个空白的仪表盘编辑器就出现在你面前了。

如果没 Docker 环境,Shaper 也提供了 npm 和 pip 包:

  • npm install @taleshape/shaper
  • pip install shaper

第 2-5 分钟:导入数据 + 写第一个查询

点击 “New Query”,写你的第一条 SQL:

-- 先看看有什么数据
SELECT * FROM read_csv_auto('sales_2024.csv') LIMIT 10;

Shaper 内置了 DuckDB 引擎,所以你可以直接用 DuckDB 的所有功能——read_csv_autoread_parquetATTACH 连接 MySQL/PostgreSQL……

然后来张真正的图表:

SELECT
  strftime(order_date, '%Y-%m')::XAXIS,
  product_category::CATEGORY,
  SUM(amount)::BARCHART_STACKED
FROM read_csv_auto('sales_2024.csv')
GROUP BY ALL ORDER BY ALL;

Shaper 自动渲染成柱状图

第 6-10 分钟:拼完整张仪表盘

再拖几个查询进来,拼出完整的仪表盘:

KPI 卡片:

SELECT
  '总销售额'::LABEL,
  '¥' || FORMAT('%,.0f', SUM(amount))::VALUE,
  '较上月 ' || CASE WHEN SUM(amount) - LAG(SUM(amount)) OVER () > 0 THEN '↑' ELSE '↓' END || FORMAT('%.1f%%', ABS((SUM(amount) - LAG(SUM(amount)) OVER ()) / LAG(SUM(amount)) OVER () * 100))::SUBTITLE
FROM read_csv_auto('sales_2024.csv');

折线趋势图:

SELECT
  order_date::XAXIS,
  SUM(amount)::LINE
FROM read_csv_auto('sales_2024.csv')
GROUP BY ALL ORDER BY ALL;

Top 10 产品:

SELECT
  product_name::LABEL,
  SUM(amount)::BARCHART
FROM read_csv_auto('sales_2024.csv')
GROUP BY ALL ORDER BY SUM(amount) DESC LIMIT 10;

十分钟,一张包含 4 个可视化组件的专业仪表盘就完成了。全部用 SQL,没有离开终端一步。


四、进阶玩法

4.1 KPI 监控 + 告警

Shaper 支持定时扫描查询结果,当指标超出阈值时自动触发告警:

-- 如果今天销售额 < 10000,触发告警
SELECT
  SUM(amount)::VALUE,
  CASE WHEN SUM(amount) < 10000 THEN '🚨 销售额低于目标'
       ELSE '✅ 正常' END::STATUS
FROM read_csv_auto('sales_2024.csv')
WHERE order_date = CURRENT_DATE;

4.2 嵌入式仪表盘

如果你想在产品中嵌入仪表盘给客户看,Shaper 支持:

  • iframe 嵌入:一行 HTML 搞定
  • JS/React SDK:无 iframe 嵌入,样式完全可控
  • 白标模式:隐藏 Shaper 品牌
<!-- iframe 嵌入方式 -->
<iframe src="https://your-shaper-instance.com/d/sales-dashboard"
        width="100%" height="600px"
        frameborder="0"></iframe>
// React SDK 方式
import { ShaperDashboard } from '@taleshape/shaper-react';

function App() {
  return <ShaperDashboard dashboardId="sales-dashboard"
                          token="your-jwt-token" />;
}

4.3 定时 PDF 报告

配置定时任务,每周一自动生成 PDF 报告并通过邮件或 Slack 发送:

# 命令行导出
curl -X POST https://your-shaper.com/api/dashboards/sales-weekly/export \
  -H "Authorization: Bearer your-token" \
  -d '{"format": "pdf"}'

五、Shaper 适合什么场景?

最适合的人群:

  • 已经用 DuckDB 做数据分析的团队
  • 需要快速出图的 SQL 分析师
  • 要给客户或管理层看可视化报表的开发者
  • 不想碰 JavaScript 的后端工程师

不太适合的场景:

  • 需要极其复杂交互(联动钻取、动画)的大屏
  • 非技术人员需要拖拽式操作(Shaper 是 SQL 驱动的)

一句话总结: 如果你已经在用 DuckDB,Shaper 是打通「查询 → 可视化 → 分享」链路的最短路径。


六、变现思路

Shaper 本身是免费开源的,但你可以围绕它做很多事情:

  1. DuckDB + Shaper 仪表盘搭建服务:帮中小企业搭建数据看板,报价 ¥3,000-8,000/次
  2. 定制嵌入式分析模块:为 SaaS 产品嵌入 Shaper 仪表盘,按月收取订阅费
  3. Shaper 中文教程系列:录制视频课程,¥99-199/套
  4. 行业模板包:预置电商/物流/财务等行业仪表盘 JSON 模板

💡 特别推荐:本教程的完整版(含 8 个实战案例 + 3 套行业仪表盘模板)已在「DuckDB 掘金实战」付费频道发布,订阅即可获取完整资源包。


七、总结

Shaper 的出现填补了 DuckDB 生态中可视化层的空白。它把「写 SQL 查数据」和「看图表做决策」之间的鸿沟填平了——你不学新工具、不写前端代码,只需要写你最擅长的 SQL。

10 分钟,从零到一张专业仪表盘。这就是 Shaper 的承诺。

立即开始:

docker run --rm -it -p5454:5454 taleshape/shaper

打开 http://localhost:5454 试试吧。