Aloudata CAN SKILLS - text-to-sql-query

👤 jackyujun 📦 v1.0.0 ⭐ 4.4 ⬇️ 808 下載
💻 開發程式設計 免費 🔑 需 API Key

📖 技能介紹


name: text-to-sql-query description: | 直接通過 Text-to-SQL 方式查詢零售資料庫。根據使用者自然語言描述,生成 SQL 查詢語句並執行。 本 Skill 不依賴語義層或指標平臺,而是直接基於資料庫 schema 生成 SQL。 觸發場景:使用者需要查詢零售資料、生成 SQL 查詢、分析銷售/客戶/商品資料時使用。


Text-to-SQL 資料查詢 Skill

根據使用者自然語言描述,直接生成 SQL 查詢語句,通過 Gateway JDBC SQL 直查介面在零售資料庫上執行並返回結果。

執行模式

  • 強模型(Claude Opus/Sonnet, GPT-4o/5):遵循"原則"段落,自行決定實現細節
  • 標準模型(Qwen, DeepSeek, Llama):嚴格按"模板"段落執行,使用提供的程式碼塊,不要自行改寫

如果你不確定自己屬於哪個類別,請按"標準模型"模式執行。


0. 查詢介面資訊

通過 Gateway JDBC SQL 直查介面執行 SQL 查詢。API Key 通過環境變數 $CAN_API_KEY 注入,禁止在 Skill 檔案中硬編碼。

0.1 介面地址

POST https://gateway.can.aloudata.com/api/jdbc/query
Content-Type: application/json
X-API-Key: $CAN_API_KEY

請求體:

{"sql": "SELECT ... FROM table_name WHERE ... LIMIT N"}

0.2 執行方式

方式一:curl(推薦,適合 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

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)

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

0.3 返回格式

成功時返回 Markdown 表格(純文本,非 JSON):

| 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 — 查詢超時

0.4 安全限制

  • 只允許 SELECT:INSERT/UPDATE/DELETE/DROP 等寫操作會被拒絕
  • 表白名單:只允許查詢 §1.1 中的 6 張表(dim_product, dim_vip, dim_shop, fact_orders, fact_inventory, fact_product_launch),查詢其他表會返回 Table not allowed 錯誤
  • 禁止多語句:不能用分號拼接多條 SQL
  • 自動加 LIMIT:未指定 LIMIT 時服務端自動追加 LIMIT 1000
  • 查詢超時:預設 30 秒超時
  • UNION 預設禁止

1. 資料庫 Schema

1.1 表結構總覽

本資料庫採用星型模型,包含 3 張事實表 + 3 張維度表。

表名 型別 說明
fact_orders 事實表 訂單明細,每行一筆訂單行專案
fact_inventory 事實表 庫存快照,每行一個 SKU 在某門店/倉庫的庫存狀態
fact_product_launch 事實表 商品上市記錄,每行一個 SKU 在某門店的上市資訊
dim_product 維度表 商品維度,SKU 級商品屬性
dim_shop 維度表 店鋪維度,門店屬性及地理資訊
dim_vip 維度表 會員維度,會員屬性資訊

1.2 事實表字段

fact_orders(訂單事實表)

欄位名 型別 說明
pay_time varchar 支付時間
delivery_date varchar 發貨日期
dt date 資料日期(分割槽鍵,用於時間篩選)
sku varchar SKU 編碼(關聯 dim_product)
shop_code varchar 接單門店編碼(關聯 dim_shop.tr_shop_code)
delivery_shop_code varchar 發貨門店編碼
vip_id bigint 會員 ID(關聯 dim_vip)
vip_code varchar 會員編碼
seller_id varchar 導購 ID
seller_code varchar 導購編碼
seller_name varchar 導購姓名
warehouse_code varchar 倉庫編碼
order_number varchar 訂單號
source_system_code varchar 來源系統編碼
order_platform_code varchar 訂單平臺編碼
retail_amount decimal(38,9) 零售金額(吊牌價口徑)
retail_quantity bigint 零售數量
retail_market_value decimal(38,9) 零售市值(吊牌額)
return_amount decimal(38,9) 退貨金額
return_quantity bigint 退貨數量
return_market_value decimal(38,9) 退貨市值
net_market_value decimal(38,9) 淨市值
net_quantity bigint 淨數量(零售數量 - 退貨數量)
net_amount decimal(38,9) 淨金額(零售金額 - 退貨金額)
unshipped_refund_quantity bigint 未發貨退款數量
unshipped_refund_amount decimal(38,9) 未發貨退款金額
shipped_refund_amount decimal(38,9) 已發貨退款金額
return_refund_quantity bigint 退貨退款數量
return_refund_amount decimal(38,9) 退貨退款金額

fact_inventory(庫存事實表)

欄位名 型別 說明
unit_code varchar 單位編碼
unit_name varchar 單位名稱
warehouse_code varchar 倉庫編碼
warehouse_name varchar 倉庫名稱
shop_code varchar 門店編碼(關聯 dim_shop.tr_shop_code)
sku varchar SKU 編碼(關聯 dim_product)
skc varchar SKC 編碼(款色)
color_code varchar 顏色編碼
color_name varchar 顏色名稱
spec_code varchar 規格編碼
spec_name varchar 規格名稱
style_code varchar 款式編碼
style_name varchar 款式名稱
stock_quantity int 庫存數量
stock_cost decimal(20,4) 庫存成本
stock_market_value decimal(20,4) 庫存市值(吊牌價口徑)
stock_quantity_onroad int 在途庫存數量
stock_cost_onroad decimal(20,4) 在途庫存成本
stock_market_value_onroad decimal(38,4) 在途庫存市值
stock_quantity_onord int 在單庫存數量
stock_cost_onord decimal(20,4) 在單庫存成本
stock_market_value_onord decimal(29,4) 在單庫存市值
stock_date date 庫存日期
snapshot_date date 快照日期(用於時間篩選)
discount_rate decimal(38,9) 折扣率

fact_product_launch(商品上市事實表)

欄位名 型別 說明
store_code varchar 門店編碼(關聯 dim_shop.tr_shop_code)
sku varchar SKU 編碼(關聯 dim_product)
skc varchar SKC 編碼(款色)
zprod_code varchar 商品編碼
brand_code varchar 品牌編碼
brand_name varchar 品牌名稱
launch_date date 上市日期
prod_year varchar 商品年份
prod_season varchar 商品季節
dt varchar 資料日期

1.3 維度表字段

dim_product(商品維度表)

欄位名 型別 說明
sku varchar SKU 編碼(主鍵)
skc varchar SKC 編碼(款色)
product_sc_type varchar 商品小類
product_sc_type_code varchar 商品小類編碼
mid_category varchar 中類
mid_category_code varchar 中類編碼
little_category varchar 小類
little_category_code varchar 小類編碼
style_code varchar 款式編碼
style_name varchar 款式名稱
age_group varchar 年齡段
age_group_code varchar 年齡段編碼
brand_id int 品牌 ID
color_code varchar 顏色編碼
color_name varchar 顏色名稱
come_up_batch varchar 上市批次
gender varchar 性別
gender_code varchar 性別編碼
price_level varchar 價格帶
product_brand_code varchar 商品品牌編碼
product_brand_name varchar(255) 商品品牌名稱
product_hierarchy varchar 商品層級
product_position_code varchar 商品定位編碼
real_market_date varchar 實際上市日期
product_year smallint 商品年份
product_season varchar 商品季節
season varchar 季節
season_code varchar 季節編碼
coefficient varchar 係數
sub_brand_id varchar(255) 子品牌 ID
tag_price decimal(20,4) 吊牌價
new_arrival_price decimal(38,9) 新品價
dt date 資料日期

dim_shop(店鋪維度表)

欄位名 型別 說明
tr_shop_code varchar 門店編碼-數倉 Key(主鍵,用於與事實表 JOIN)
shop_code varchar 門店編碼(業務編碼)
shop_id bigint 門店 ID
shop_brand_id bigint 門店品牌 ID
shop_leader varchar 店長姓名
shop_leader_code varchar 店長編碼
shop_status varchar 門店狀態
shop_status_code varchar 門店狀態編碼
province varchar 省份
province_id bigint 省份 ID
city varchar 城市
city_id bigint 城市 ID
city_grade varchar 城市等級
city_grade_id bigint 城市等級 ID
district varchar 區縣
address varchar 地址
shop_name varchar 門店名稱
business_area int 營業面積
business_district_level varchar 商圈等級
business_district_level_code varchar 商圈等級編碼
first_channel varchar 一級渠道
first_channel_id bigint 一級渠道 ID
first_channel_code varchar 一級渠道編碼
second_channel varchar 二級渠道
second_channel_id bigint 二級渠道 ID
second_channel_code varchar 二級渠道編碼
channel_type_id bigint 渠道型別 ID
opening_date varchar 開店日期
closing_date varchar 閉店日期
dt date 資料日期

dim_vip(會員維度表)

欄位名 型別 說明
dt date 資料日期
vip_id bigint 會員 ID(主鍵)
vip_code varchar 會員編碼
vip_name varchar 會員姓名
vip_level varchar 會員等級
vip_level_code varchar 會員等級編碼
vip_status varchar 會員狀態
vip_status_code varchar 會員狀態編碼
vip_reg_date varchar 註冊日期
vip_last_login_date varchar 最後登入日期

1.4 表間關係(JOIN 規範)

-- 訂單表關聯維度表
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 關鍵注意事項: - dim_shop 的主鍵是 tr_shop_code(數倉 Key),不是 shop_code(業務編碼)。事實表中的 shop_code / store_code 對應的是 dim_shop.tr_shop_code - dim_vip 的主鍵是 vip_id(bigint),與 fact_orders 的 vip_id 關聯 - dim_product 的主鍵是 sku,三張事實表都通過 sku 欄位關聯 - 本資料庫沒有獨立的日期維度表,時間篩選直接使用事實表的 dt(date 型別)或 snapshot_date 欄位


常用 SQL 查詢模板(標準模型:直接複製修改)

模板 1:上月某指標的彙總值

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');

模板 2:上月各渠道的銷售額及環比

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;

模板 3:Top-N 品牌排名

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;

模板 4:某維度在全域性的佔比

小蔥技能站7w4.net,專業的AI技能分享平臺。

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;

模板 5:日趨勢查詢

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_FORMATDATE_SUBCURDATE() 等標準函式 - 視窗函式(OVER())完全支援 - NULLIF 用於避免除零錯誤


2. 語義理解(SQL 生成前必做)

在寫任何 SQL 之前,先把使用者的問題拆解為四個維度:

維度 問自己 示例
看什麼(指標) 使用者要看的業務量是什麼? "銷售額""客單價""庫存量"
怎麼看(分析方式) 直接看值?還是要對比/佔比/排名/趨勢? "同比增長率""佔比""排名前5""月趨勢"
看誰的(維度 & 篩選) 按什麼維度拆分?篩選哪些範圍? "各品牌""某渠道""某地區"
看哪段時間(時間) 時間範圍是什麼? "上月""近7天""某月 vs 另一月"

2.1 從 Schema 推斷指標

本資料庫沒有統一的指標定義層。你需要根據 §1 中的表結構和欄位說明,自行推斷使用者業務術語對應的 SQL 寫法。

⚠️ 這是 Text-to-SQL 最容易出錯的環節。以下是常見的歧義陷阱,務必留意:

陷阱 A — 金額口徑歧義:fact_orders 中有多個金額欄位(retail_amount、net_amount、retail_market_value 等),使用者說"銷售額"時到底指哪個?不同口徑的差異可能很大。當無法確定時,應在查詢解讀中說明你採用的口徑。

陷阱 B — 複合指標的計算方式:像"客單價""連帶率""件單價""折扣率""退貨率"這類複合指標,需要你根據業務含義自行組合欄位計算。同一個術語可能有多種合理的計算方式(例如"客單價"的分母是人數還是單數?),不同演算法的結果可能相差數十倍。

陷阱 C — 跨表指標:有些指標可能涉及多張表的資料(如庫存相關指標在 fact_inventory,銷售相關在 fact_orders)。注意判斷指標來自哪張表,不要在錯誤的表上查詢。

陷阱 D — 資料庫能力邊界:本資料庫是零售訂單、庫存和商品資料,不包含所有業務資料。如果使用者詢問的指標在現有表中找不到對應欄位,應如實告知,不要強行拼湊。

2.2 關鍵語義消歧規則

規則 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 和視窗函式。


3. SQL 生成規範

3.1 JOIN 規則

  • 只 JOIN 需要的表,不要多餘 JOIN
  • 使用 LEFT JOIN 保證事實表資料不丟失
  • 維度表字段用於 SELECT/WHERE/GROUP BY 時才 JOIN 對應維度表
  • dim_shop 關聯用 tr_shop_code,不要用 shop_code
-- 示例:按一級渠道查銷售額
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;
-- 示例:按品牌查銷售額
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;
-- 示例:按會員等級查購買人數
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;

3.2 時間處理

時間欄位說明: - fact_orders 用 dt(date 型別)做時間篩選 - fact_inventory 用 snapshot_date(date 型別)做時間篩選 - fact_product_launch 用 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')

3.3 同環比計算

同環比需要用 CTE 或子查詢分別獲取兩個時期的資料再對比:

-- 月環比示例:上月 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:

-- 各渠道月環比
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;

3.4 佔比計算

-- 各渠道銷售額佔比
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;

3.5 排名計算

-- 品牌銷售額 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;

4. 輸出規範

每次執行查詢時,必須按以下三段式結構向用戶展示資訊,缺一不可,順序不可顛倒:

4.1 📊 查詢解讀(自然語言,放在最前面)

用一段自然語言向用戶解釋"查了什麼、怎麼查的",讓非技術使用者也能理解查詢含義。

寫作要求: - 用一段連貫的話描述,不要用列表 - 涵蓋以下要素:查了什麼指標、什麼時間範圍、按什麼維度拆分、有什麼篩選條件、做了什麼計算 - 簡單查詢簡短說(1~2句),複雜查詢可以多說幾句

4.2 📋 SQL 查詢語句

展示完整的、格式化的 SQL 語句:

SELECT ...
FROM ...
WHERE ...
GROUP BY ...
ORDER BY ...;

4.3 📈 查詢結果

以表格形式展示查詢返回的資料結果。列名使用中文展示名。

4.4 完整輸出示例

示例 A — 簡單查詢:使用者問"上月的銷售額是多少?"

📊 查詢解讀

幫你查詢了上月(2026年2月)的零售金額(retail_amount 求和),查的是整體總量,沒有按維度拆分。

📋 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 查詢語句:

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,567 | 4,426,012 | +18.3% | | 直營 | 3,456,789 | 3,083,754 | +12.1% | | ... | ... | ... | ... |


5. SQL 生成流程

步驟 0:語義解析

按 §2 將使用者問題拆解為"看什麼 / 怎麼看 / 看誰的 / 看哪段時間"四維度。檢查 §2.2 的消歧規則。

步驟 1:確定指標和表

  • 根據 §2.1 的對映表,確定需要的 SQL 聚合表示式
  • 確定涉及哪些事實表(fact_orders / fact_inventory / fact_product_launch)
  • ⚠️ 當指標存在歧義時(如"銷售額"可能是 retail_amount 或 net_amount,"客單價"有多種演算法),應在查詢解讀中說明所採用的口徑,或主動詢問使用者

步驟 2:確定維度和 JOIN

  • 根據使用者需要的分組維度,確定需要 JOIN 哪些維度表
  • 按 §1.4 的關係進行 JOIN
  • 特別注意:渠道/地區維度在 dim_shop 中,品類/品牌維度在 dim_product 中,會員維度在 dim_vip 中

步驟 3:構建時間條件

  • 按 §3.2 將使用者的時間描述轉為 WHERE 條件
  • 使用者未指定時間時的預設策略:
  • 有同環比 → 預設上月
  • 有趨勢 → 預設近12個月
  • 有排名/TOP-N → 預設上月
  • 其他 → 預設近7天

步驟 4:構建聚合和計算

  • 同環比 → CTE 分兩期查詢再 JOIN(§3.3)
  • 佔比 → 視窗函式(§3.4)
  • 排名 → 視窗函式(§3.5)

步驟 5:SQL 自檢

生成 SQL 後,逐項檢查: - ✅ 輸出結構為三段式:📊 查詢解讀 → 📋 SQL → 📈 結果 - ✅ 所有 JOIN 條件正確:fact_orders.shop_code = dim_shop.tr_shop_code(不是 shop_code) - ✅ WHERE 條件中時間範圍正確(左閉右開) - ✅ GROUP BY 包含所有非聚合列 - ✅ NULLIF 處理除零問題 - ✅ 聚合函式與業務含義一致(SUM vs COUNT DISTINCT vs AVG) - ✅ 列別名使用中文展示名

步驟 6:執行並展示

通過 §0 的 Gateway JDBC API 執行 SQL,按 §4 的三段式格式展示結果。

執行注意事項: - API 返回的是 Markdown 表格純文本,直接展示給使用者即可 - 如遇 Table not allowed 錯誤,說明查詢了白名單以外的表,檢查 §1.1 的可用表列表 - 如遇查詢超時(30 秒),考慮縮小時間範圍或加更嚴格的 WHERE 條件 - SQL 中字串值用單引號包裹(如 WHERE sku = 'SKU1000211') - 始終顯式加 LIMIT,避免依賴服務端自動 LIMIT 1000


6. 常見錯誤模式

❌ 模式 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:維度值不確定 不知道維度表中具體有哪些值(如一級渠道到底有哪些),應先查詢確認:

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


7. 侷限性宣告

本 Skill 直接基於資料庫 schema 生成 SQL,存在以下固有侷限:

  1. 指標口徑無統一定義:同一業務概念(如"客單價")可能有多種 SQL 實現,需要人工確認
  2. 無內建快速計算:同環比、佔比、排名等分析計算需要手寫複雜 SQL(CTE/視窗函式)
  3. 無維度值後設資料:不知道維度表中具體有哪些值,需要先查詢確認
  4. 無業務語義層:資料庫欄位註釋不足以表達完整的業務語義(如"銷售額"到底用哪個金額欄位)
  5. 無獨立流量表:本資料庫無流量資料(UV/PV),無法計算轉化率等跨表指標
  6. 無日期維度表:時間屬性(年/季/月/周/是否週末等)需要通過 SQL 日期函式實現

🤖 AI 評測

這個Skill整體質量較好,能較準確地根據自然語言生成SQL查詢零售資料,文件結構完整、示例豐富、安全限制明確。主要優點是提供了詳細的資料庫表結構和多種查詢模板;不足之處是某些業務術語(如客單價)的計算方式可能存在歧義,需要使用者自行確認口徑。總體而言是一個可用性較高的資料查詢工具。

📊 多維度評分

適應性4.3
規範性4.1
有效性4.5
可靠性4.2
可信度5

📁 包含檔案 (2 個)

📄 SKILL.md 30.2 KB
📄 _meta.json 136 B