使用 Text-to-SQL 直接查询零售数据库;根据自然语言生成并执行 SQL,不依赖语义层或指标平台,直接基于库 schema。适用场景:查询零售数据、生成 SQL、分析销售/客户/商品。
根据用户自然语言描述,直接生成 SQL 查询语句,通过 Gateway JDBC SQL 直查接口在零售数据库上执行并返回结果。
如果你不确定自己属于哪个类别,请按"标准模型"模式执行。
通过 Gateway JDBC SQL 直查接口执行 SQL 查询。API Key 通过环境变量 $CAN_API_KEY 注入,禁止在 Skill 文件中硬编码。
text
POST https://gateway.can.aloudata.com/api/jdbc/query
Content-Type: application/json
X-API-Key: $CAN_API_KEY
请求体:
json
{"sql": "SELECT ... FROM table_name WHERE ... LIMIT N"}
方式一:curl(推荐,适合 Bash 环境)
bash
curl --noproxy '*' -s \
-H "X-API-Key: $CAN_API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://gateway.can.aloudata.com/api/jdbc/query" \
-d '{"sql": "YOUR SQL HERE"}'
方式二:Python requests
python
import os, requests
response = requests.post(
"https://gateway.can.aloudata.com/api/jdbc/query",
headers={
"X-API-Key": os.environ["CAN_API_KEY"],
"Content-Type": "application/json"
},
json={"sql": "YOUR SQL HERE"}
)
print(response.text) # 返回 Markdown 表格(纯文本)
多行 SQL 示例(curl heredoc):
bash
curl --noproxy '*' -s \
-H "X-API-Key: $CAN_API_KEY" \
-H "Content-Type: application/json" \
-X POST "https://gateway.can.aloudata.com/api/jdbc/query" \
-d @- <<'EOF'
{"sql": "SELECT o.dt, o.order_number, p.style_name, s.shop_name, o.retail_amount FROM fact_orders o JOIN dim_product p ON o.sku = p.sku JOIN dim_shop s ON o.shop_code = s.tr_shop_code WHERE o.dt >= '2024-01-01' ORDER BY o.dt DESC LIMIT 20"}
EOF
成功时 返回 Markdown 表格(纯文本,非 JSON):
text
| sku | style_name | color_name | tag_price |
| --- | --- | --- | --- |
| SKU1000211 | 泡泡袖衬衫春秋款 | 白色 | 118.8600 |
| SKU1000222 | 背带裤明星同款 | 灰色 | 439.1300 |
2 row(s) returned.
错误时 返回纯文本错误信息:
SQL validation error: Table not allowed: xxx — 查询了白名单以外的表SQL validation error: Only SELECT statements are allowed — 非 SELECT 语句Query error: Query timed out after 30 seconds — 查询超时Table not allowed 错误本数据库采用 星型模型,包含 3 张事实表 + 3 张维度表。
表名类型说明fact_orders事实表订单明细,每行一笔订单行项目fact_inventory事实表库存快照,每行一个 SKU 在某门店/仓库的库存状态fact_product_launch事实表商品上市记录,每行一个 SKU 在某门店的上市信息dim_product维度表商品维度,SKU 级商品属性dim_shop维度表店铺维度,门店属性及地理信息dim_vip维度表会员维度,会员属性信息
字段名类型说明pay_timevarchar支付时间delivery_datevarchar发货日期dtdate数据日期(分区键,用于时间筛选)skuvarcharSKU 编码(关联 dim_product)shop_codevarchar接单门店编码(关联 dim_shop.tr_shop_code)delivery_shop_codevarchar发货门店编码vip_idbigint会员 ID(关联 dim_vip)vip_codevarchar会员编码seller_idvarchar导购 IDseller_codevarchar导购编码seller_namevarchar导购姓名warehouse_codevarchar仓库编码order_numbervarchar订单号source_system_codevarchar来源系统编码order_platform_codevarchar订单平台编码retail_amountdecimal(38,9)零售金额(吊牌价口径)retail_quantitybigint零售数量retail_market_valuedecimal(38,9)零售市值(吊牌额)return_amountdecimal(38,9)退货金额return_quantitybigint退货数量return_market_valuedecimal(38,9)退货市值net_market_valuedecimal(38,9)净市值net_quantitybigint净数量(零售数量 - 退货数量)net_amountdecimal(38,9)净金额(零售金额 - 退货金额)unshipped_refund_quantitybigint未发货退款数量unshipped_refund_amountdecimal(38,9)未发货退款金额shipped_refund_amountdecimal(38,9)已发货退款金额return_refund_quantitybigint退货退款数量return_refund_amountdecimal(38,9)退货退款金额
字段名类型说明unit_codevarchar单位编码unit_namevarchar单位名称warehouse_codevarchar仓库编码warehouse_namevarchar仓库名称shop_codevarchar门店编码(关联 dim_shop.tr_shop_code)skuvarcharSKU 编码(关联 dim_product)skcvarcharSKC 编码(款色)color_codevarchar颜色编码color_namevarchar颜色名称spec_codevarchar规格编码spec_namevarchar规格名称style_codevarchar款式编码style_namevarchar款式名称stock_quantityint库存数量stock_costdecimal(20,4)库存成本stock_market_valuedecimal(20,4)库存市值(吊牌价口径)stock_quantity_onroadint在途库存数量stock_cost_onroaddecimal(20,4)在途库存成本stock_market_value_onroaddecimal(38,4)在途库存市值stock_quantity_onordint在单库存数量stock_cost_onorddecimal(20,4)在单库存成本stock_market_value_onorddecimal(29,4)在单库存市值stock_datedate库存日期snapshot_datedate快照日期(用于时间筛选)discount_ratedecimal(38,9)折扣率
字段名类型说明store_codevarchar门店编码(关联 dim_shop.tr_shop_code)skuvarcharSKU 编码(关联 dim_product)skcvarcharSKC 编码(款色)zprod_codevarchar商品编码brand_codevarchar品牌编码brand_namevarchar品牌名称launch_datedate上市日期prod_yearvarchar商品年份prod_seasonvarchar商品季节dtvarchar数据日期
字段名类型说明skuvarcharSKU 编码(主键)skcvarcharSKC 编码(款色)product_sc_typevarchar商品小类product_sc_type_codevarchar商品小类编码mid_categoryvarchar中类mid_category_codevarchar中类编码little_categoryvarchar小类little_category_codevarchar小类编码style_codevarchar款式编码style_namevarchar款式名称age_groupvarchar年龄段age_group_codevarchar年龄段编码brand_idint品牌 IDcolor_codevarchar颜色编码color_namevarchar颜色名称come_up_batchvarchar上市批次gendervarchar性别gender_codevarchar性别编码price_levelvarchar价格带product_brand_codevarchar商品品牌编码product_brand_namevarchar(255)商品品牌名称product_hierarchyvarchar商品层级product_position_codevarchar商品定位编码real_market_datevarchar实际上市日期product_yearsmallint商品年份product_seasonvarchar商品季节seasonvarchar季节season_codevarchar季节编码coefficientvarchar系数sub_brand_idvarchar(255)子品牌 IDtag_pricedecimal(20,4)吊牌价new_arrival_pricedecimal(38,9)新品价dtdate数据日期
字段名类型说明tr_shop_codevarchar门店编码-数仓 Key(主键,用于与事实表 JOIN)shop_codevarchar门店编码(业务编码)shop_idbigint门店 IDshop_brand_idbigint门店品牌 IDshop_leadervarchar店长姓名shop_leader_codevarchar店长编码shop_statusvarchar门店状态shop_status_codevarchar门店状态编码provincevarchar省份province_idbigint省份 IDcityvarchar城市city_idbigint城市 IDcity_gradevarchar城市等级city_grade_idbigint城市等级 IDdistrictvarchar区县addressvarchar地址shop_namevarchar门店名称business_areaint营业面积business_district_levelvarchar商圈等级business_district_level_codevarchar商圈等级编码first_channelvarchar一级渠道first_channel_idbigint一级渠道 IDfirst_channel_codevarchar一级渠道编码second_channelvarchar二级渠道second_channel_idbigint二级渠道 IDsecond_channel_codevarchar二级渠道编码channel_type_idbigint渠道类型 IDopening_datevarchar开店日期closing_datevarchar闭店日期dtdate数据日期
字段名类型说明dtdate数据日期vip_idbigint会员 ID(主键)vip_codevarchar会员编码vip_namevarchar会员姓名vip_levelvarchar会员等级vip_level_codevarchar会员等级编码vip_statusvarchar会员状态vip_status_codevarchar会员状态编码vip_reg_datevarchar注册日期vip_last_login_datevarchar最后登录日期
text
-- 订单表关联维度表
fact_orders.sku = dim_product.sku
fact_orders.shop_code = dim_shop.tr_shop_code
fact_orders.vip_id = dim_vip.vip_id
-- 库存表关联维度表
fact_inventory.sku = dim_product.sku
fact_inventory.shop_code = dim_shop.tr_shop_code
-- 商品上市表关联维度表
fact_product_launch.sku = dim_product.sku
fact_product_launch.store_code = dim_shop.tr_shop_code
⚠️ JOIN 关键注意事项:
tr_shop_code(数仓 Key),不是 shop_code(业务编码)。事实表中的 shop_code / store_code 对应的是 dim_shop.tr_shop_codevip_id(bigint),与 fact_orders 的 vip_id 关联sku,三张事实表都通过 sku 字段关联dt(date 类型)或 snapshot_date 字段sql
SELECT
SUM(retail_amount) AS total_sales
FROM fact_orders
WHERE dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND dt < DATE_FORMAT(CURDATE(), '%Y-%m-01');
sql
WITH current_month AS (
SELECT
ds.first_channel,
SUM(fo.retail_amount) AS sales
FROM fact_orders fo
JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND fo.dt < DATE_FORMAT(CURDATE(), '%Y-%m-01')
GROUP BY ds.first_channel
),
previous_month AS (
SELECT
ds.first_channel,
SUM(fo.retail_amount) AS sales
FROM fact_orders fo
JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 2 MONTH), '%Y-%m-01')
AND fo.dt < DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
GROUP BY ds.first_channel
)
SELECT
c.first_channel,
c.sales AS current_sales,
p.sales AS previous_sales,
(c.sales - p.sales) / NULLIF(p.sales, 0) AS mom_growth
FROM current_month c
LEFT JOIN previous_month p ON c.first_channel = p.first_channel
ORDER BY c.sales DESC;
sql
SELECT
dp.product_brand_name,
SUM(fo.retail_amount) AS total_sales,
COUNT(DISTINCT fo.order_number) AS order_count,
SUM(fo.retail_amount) / NULLIF(COUNT(DISTINCT fo.vip_id), 0) AS aov
FROM fact_orders fo
JOIN dim_product dp ON fo.sku = dp.sku
WHERE fo.dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND fo.dt < DATE_FORMAT(CURDATE(), '%Y-%m-01')
GROUP BY dp.product_brand_name
ORDER BY total_sales DESC
LIMIT 10;
sql
SELECT
ds.first_channel,
SUM(fo.retail_amount) AS channel_sales,
SUM(fo.retail_amount) / SUM(SUM(fo.retail_amount)) OVER () AS sales_proportion
FROM fact_orders fo
JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND fo.dt < DATE_FORMAT(CURDATE(), '%Y-%m-01')
GROUP BY ds.first_channel
ORDER BY channel_sales DESC;
sql
SELECT
fo.dt,
SUM(fo.retail_amount) AS daily_sales
FROM fact_orders fo
WHERE fo.dt >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
AND fo.dt < CURDATE()
GROUP BY fo.dt
ORDER BY fo.dt;
⚠️ StarRocks 兼容性提示:StarRocks 兼容 MySQL 语法,但注意:
- 使用
DATE_FORMAT、DATE_SUB、CURDATE()等标准函数- 窗口函数(
OVER())完全支持NULLIF用于避免除零错误
在写任何 SQL 之前,先把用户的问题拆解为四个维度:
维度问自己示例看什么(指标)用户要看的业务量是什么?"销售额""客单价""库存量"怎么看(分析方式)直接看值?还是要对比/占比/排名/趋势?"同比增长率""占比""排名前5""月趋势"看谁的(维度 & 筛选)按什么维度拆分?筛选哪些范围?"各品牌""某渠道""某地区"看哪段时间(时间)时间范围是什么?"上月""近7天""某月 vs 另一月"
本数据库没有统一的指标定义层。你需要根据 §1 中的表结构和字段说明,自行推断用户业务术语对应的 SQL 写法。
⚠️ 这是 Text-to-SQL 最容易出错的环节。以下是常见的歧义陷阱,务必留意:
陷阱 A — 金额口径歧义:fact_orders 中有多个金额字段(retail_amount、net_amount、retail_market_value 等),用户说"销售额"时到底指哪个?不同口径的差异可能很大。当无法确定时,应在查询解读中说明你采用的口径。
陷阱 B — 复合指标的计算方式:像"客单价""连带率""件单价""折扣率""退货率"这类复合指标,需要你根据业务含义自行组合字段计算。同一个术语可能有多种合理的计算方式(例如"客单价"的分母是人数还是单数?),不同算法的结果可能相差数十倍。
陷阱 C — 跨表指标:有些指标可能涉及多张表的数据(如库存相关指标在 fact_inventory,销售相关在 fact_orders)。注意判断指标来自哪张表,不要在错误的表上查询。
陷阱 D — 数据库能力边界:本数据库是零售订单、库存和商品数据,不包含所有业务数据。如果用户询问的指标在现有表中找不到对应字段,应如实告知,不要强行拼凑。
规则 A — "总和" vs "分别"
用户说含义GROUP BY"A 和 B 的某指标分别是多少"按 A、B 分组展示保留分组"A 和 B 的某指标总和"A+B 合并为一个数字不分组"A 和 B 的某指标"(无修饰)默认"分别"保留分组
规则 B — "占比" 的两种含义
用户说含义SQL 实现"某指标占比"(如"销售额占比")值占比SUM(x) / SUM(SUM(x)) OVER()"某实体占比"(如"款色占比")数量占比COUNT(DISTINCT entity) / (SELECT COUNT(DISTINCT entity) FROM ...)
规则 C — "同比" vs "环比"
用户说含义SQL 实现"同比"(无限定)年同比 (YoY)与去年同期对比"月同比"与上月同期对比上个月的同日/同周"环比"与上一个周期对比根据粒度:日→前一天,月→前一月
规则 D — 简单优先
如果用户问题可以用简单 SQL 回答,就不要写复杂的 CTE 和窗口函数。
tr_shop_code,不要用 shop_codesql
-- 示例:按一级渠道查销售额
SELECT ds.first_channel, SUM(fo.retail_amount) AS retail_amt
FROM fact_orders fo
LEFT JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= '2026-02-01' AND fo.dt < '2026-03-01'
GROUP BY ds.first_channel
ORDER BY retail_amt DESC;
sql
-- 示例:按品牌查销售额
SELECT dp.product_brand_name, SUM(fo.retail_amount) AS retail_amt
FROM fact_orders fo
LEFT JOIN dim_product dp ON fo.sku = dp.sku
WHERE fo.dt >= '2026-02-01' AND fo.dt < '2026-03-01'
GROUP BY dp.product_brand_name
ORDER BY retail_amt DESC;
sql
-- 示例:按会员等级查购买人数
SELECT dv.vip_level, COUNT(DISTINCT fo.vip_id) AS vip_count
FROM fact_orders fo
LEFT JOIN dim_vip dv ON fo.vip_id = dv.vip_id
WHERE fo.dt >= '2026-02-01' AND fo.dt < '2026-03-01'
GROUP BY dv.vip_level
ORDER BY vip_count DESC;
时间字段说明:
dt(date 类型)做时间筛选snapshot_date(date 类型)做时间筛选launch_date(date 类型)做时间筛选相对时间转换:
用户说WHERE 条件上月dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01') AND dt < DATE_FORMAT(CURDATE(), '%Y-%m-01')本月dt >= DATE_FORMAT(CURDATE(), '%Y-%m-01') AND dt < DATE_ADD(DATE_FORMAT(CURDATE(), '%Y-%m-01'), INTERVAL 1 MONTH)昨天dt = DATE_SUB(CURDATE(), INTERVAL 1 DAY)近7天dt >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND dt < CURDATE()近30天dt >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND dt < CURDATE()本年dt >= DATE_FORMAT(CURDATE(), '%Y-01-01')去年dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 YEAR), '%Y-01-01') AND dt < DATE_FORMAT(CURDATE(), '%Y-01-01')
同环比需要用 CTE 或子查询分别获取两个时期的数据再对比:
sql
-- 月环比示例:上月 vs 上上月整体销售额
WITH current_month AS (
SELECT SUM(retail_amount) AS current_val
FROM fact_orders
WHERE dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND dt < DATE_FORMAT(CURDATE(), '%Y-%m-01')
),
previous_month AS (
SELECT SUM(retail_amount) AS previous_val
FROM fact_orders
WHERE dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 2 MONTH), '%Y-%m-01')
AND dt < DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
)
SELECT
cm.current_val,
pm.previous_val,
cm.current_val - pm.previous_val AS change_value,
(cm.current_val - pm.previous_val) / NULLIF(pm.previous_val, 0) AS growth_rate
FROM current_month cm, previous_month pm;
按维度拆分的同环比更加复杂,需要用 FULL JOIN:
sql
-- 各渠道月环比
WITH current_month AS (
SELECT ds.first_channel, SUM(fo.retail_amount) AS current_val
FROM fact_orders fo
LEFT JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND fo.dt < DATE_FORMAT(CURDATE(), '%Y-%m-01')
GROUP BY ds.first_channel
),
previous_month AS (
SELECT ds.first_channel, SUM(fo.retail_amount) AS previous_val
FROM fact_orders fo
LEFT JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 2 MONTH), '%Y-%m-01')
AND fo.dt < DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
GROUP BY ds.first_channel
)
SELECT
COALESCE(cm.first_channel, pm.first_channel) AS `一级渠道`,
cm.current_val AS `本月销售金额`,
pm.previous_val AS `上月销售金额`,
(cm.current_val - pm.previous_val) / NULLIF(pm.previous_val, 0) AS `月环比增长率`
FROM current_month cm
FULL JOIN previous_month pm ON cm.first_channel = pm.first_channel
ORDER BY `月环比增长率` DESC;
sql
-- 各渠道销售额占比
SELECT
ds.first_channel,
SUM(fo.retail_amount) AS retail_amt,
SUM(fo.retail_amount) / SUM(SUM(fo.retail_amount)) OVER() AS proportion
FROM fact_orders fo
LEFT JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND fo.dt < DATE_FORMAT(CURDATE(), '%Y-%m-01')
GROUP BY ds.first_channel
ORDER BY retail_amt DESC;
sql
-- 品牌销售额 TOP 5
SELECT
dp.product_brand_name,
SUM(fo.retail_amount) AS retail_amt,
RANK() OVER(ORDER BY SUM(fo.retail_amount) DESC) AS rk
FROM fact_orders fo
LEFT JOIN dim_product dp ON fo.sku = dp.sku
WHERE fo.dt >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
AND fo.dt < DATE_FORMAT(CURDATE(), '%Y-%m-01')
GROUP BY dp.product_brand_name
ORDER BY retail_amt DESC
LIMIT 5;
每次执行查询时,必须按以下 三段式结构 向用户展示信息,缺一不可,顺序不可颠倒:
用一段自然语言向用户解释"查了什么、怎么查的",让非技术用户也能理解查询含义。
写作要求:
展示完整的、格式化的 SQL 语句:
sql
SELECT ...
FROM ...
WHERE ...
GROUP BY ...
ORDER BY ...;
以表格形式展示查询返回的数据结果。列名使用中文展示名。
示例 A — 简单查询:用户问"上月的销售额是多少?"
📊 查询解读
帮你查询了上月(2026年2月)的零售金额(retail_amount 求和),查的是整体总量,没有按维度拆分。
📋 SQL 查询语句:
sql
SELECT SUM(retail_amount) AS `零售金额`
FROM fact_orders
WHERE dt >= '2026-02-01' AND dt < '2026-03-01';
📈 查询结果: 上月(2026年2月)的零售金额为 12,345,678 元。
示例 B — 带维度和环比的复杂查询:用户问"上月各渠道的销售额及月环比增长率,增速前5名是哪些?"
📊 查询解读
帮你查询了上月(2026年2月)各一级渠道的零售金额(retail_amount 求和),并用 CTE 分别计算了本月和上月的数据后做对比,得出月环比增长率。结果按环比增长率从高到低排列,取前 5 名。
📋 SQL 查询语句:
sql
WITH current_month AS (
SELECT ds.first_channel, SUM(fo.retail_amount) AS current_val
FROM fact_orders fo
LEFT JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= '2026-02-01' AND fo.dt < '2026-03-01'
GROUP BY ds.first_channel
),
previous_month AS (
SELECT ds.first_channel, SUM(fo.retail_amount) AS previous_val
FROM fact_orders fo
LEFT JOIN dim_shop ds ON fo.shop_code = ds.tr_shop_code
WHERE fo.dt >= '2026-01-01' AND fo.dt < '2026-02-01'
GROUP BY ds.first_channel
)
SELECT
COALESCE(cm.first_channel, pm.first_channel) AS `一级渠道`,
cm.current_val AS `本月零售金额`,
pm.previous_val AS `上月零售金额`,
(cm.current_val - pm.previous_val) / NULLIF(pm.previous_val, 0) AS `月环比增长率`
FROM current_month cm
FULL JOIN previous_month pm ON cm.first_channel = pm.first_channel
ORDER BY `月环比增长率` DESC
LIMIT 5;
📈 查询结果:
一级渠道本月零售金额上月零售金额月环比增长率电商5,234,5674,426,012+18.3%直营3,456,7893,083,754+12.1%............
按 §2 将用户问题拆解为"看什么 / 怎么看 / 看谁的 / 看哪段时间"四维度。检查 §2.2 的消歧规则。
生成 SQL 后,逐项检查:
通过 §0 的 Gateway JDBC API 执行 SQL,按 §4 的三段式格式展示结果。
执行注意事项:
Table not allowed 错误,说明查询了白名单以外的表,检查 §1.1 的可用表列表WHERE sku = 'SKU1000211')❌ 模式 1:金额字段选错 retail_amount(零售金额)和 net_amount(净销售金额)差异可能很大。必须确认用户意图。
❌ 模式 2:客单价算法歧义
SUM(retail_amount) / COUNT(DISTINCT vip_id) = 人均消费金额SUM(retail_amount) / COUNT(DISTINCT order_number) = 单均金额❌ 模式 3:dim_shop JOIN 键用错
事实表的 shop_code 对应 dim_shop 的 tr_shop_code(数仓 Key), 不是 dim_shop 的 shop_code(业务编码)。这是最容易犯的错误。
❌ 模式 4:同环比时间范围写错 手动计算两个时期的时间范围容易出错,特别是跨年、跨月场景。
❌ 模式 5:维度值不确定 不知道维度表中具体有哪些值(如一级渠道到底有哪些),应先查询确认:
sql
SELECT DISTINCT first_channel FROM dim_shop;
SELECT DISTINCT product_brand_name FROM dim_product;
SELECT DISTINCT vip_level FROM dim_vip;
❌ 模式 6:缺少行业术语理解 数据库 schema 不包含业务语义。例如"动销率""售罄率""库销比"等行业指标,纯靠 schema 无法推断其计算公式。
❌ 模式 7:GROUP BY 缺失列 SELECT 中有非聚合列但 GROUP BY 中遗漏,在严格模式下会报错。
❌ 模式 8:除零错误 环比增长率等计算中,分母可能为 0 或 NULL,必须用 NULLIF 处理。
❌ 模式 9:库存表时间字段用错
fact_inventory 的时间筛选用 snapshot_date,不是 dt(该表无 dt 字段)。fact_orders 的时间筛选用 dt。
本 Skill 直接基于数据库 schema 生成 SQL,存在以下固有局限: