Business question · SQL pattern · result verification业务问题 · SQL 模式 · 结果验证

SQL Query Examples: From Questions to ResultsSQL 查询实例:12 个中文业务问题与完整语句

Learn twelve reusable SQL patterns through one synthetic commerce schema, with precise natural-language questions, result grain, dialect notes, and checks that catch plausible but wrong answers.

围绕同一套合成电商 Schema,完整演示筛选、连接、聚合、CTE 和窗口函数等 12 类查询;每个实例都从中文业务问题开始,给出结果粒度、SQL、方言说明和验证检查。

Updated July 30, 2026更新于 2026 年 7 月 30 日38 min read阅读约 38 分钟InfiniSynapse Editorial TeamInfiniSynapse 数据团队
SQL 查询实例流程:中文业务问题经过四表关系 Schema 转换为完整 SQL、结果表格与五项验证检查
On this page本文目录

What makes an SQL query example useful?什么样的 SQL 查询实例才真正有用?

A useful SQL query example connects a specific data question to a known schema, states the intended row grain, shows the complete query, and explains how to verify the result. Syntax alone is not enough. A query can parse successfully and still choose the wrong population, multiply revenue through a many-to-many join, exclude zero-activity entities, mishandle date boundaries, or return a nondeterministic top-N result.

高质量 SQL 查询实例必须同时给出业务问题、已知 Schema、结果行粒度、完整语句和验证方法。只有 SQL 代码远远不够:语句即使能执行,也可能选错统计总体、因多对多连接放大收入、遗漏零活动实体、错误处理日期边界,或返回不稳定的 Top-N 结果。

This guide uses twelve read-only PostgreSQL-style examples over one synthetic commerce model. The patterns are broadly recognizable across PostgreSQL, MySQL, BigQuery, Snowflake, SQL Server, and other systems, but functions, quoting, parameters, date arithmetic, and window-filter syntax differ. Treat every example as a reasoning pattern to adapt—not production-ready code for an unknown database.

本文围绕一套合成电商模型,给出十二个只读、偏 PostgreSQL 风格的示例。PostgreSQL、MySQL、BigQuery、Snowflake、SQL Server 等系统大多能识别这些模式,但函数、引号、参数、日期运算和窗口过滤语法并不完全一致。请把每个示例视为需要适配的推理模式,而不是可以直接用于未知数据库的生产代码。

Scope and safety:范围与安全: all names and figures are synthetic. Run adapted queries in a read-only development or analytics environment first. Do not paste credentials, secrets, personal data, or proprietary row values into a public demo.所有名称与数字均为合成示例。适配后的查询应先在只读开发或分析环境中运行;不要把凭据、密钥、个人数据或专有行值粘贴到公开演示工具。

Use one explicit schema for all twelve SQL query examples十二个 SQL 查询示例共用一套明确 Schema

Examples become easier to compare when tables, keys, units, and time fields stay stable. The synthetic model below represents customers placing orders that contain products. Payments are separated from orders because one order may have multiple attempts, refunds, or settlements. Monetary examples use the order header's total_amount unless the question explicitly requires item-level economics.

当表、键、单位和时间字段保持稳定时,不同示例才容易比较。下面的合成模型表示客户下单、订单包含商品;付款与订单分开,因为一个订单可能对应多次尝试、退款或结算。除非问题明确要求商品行级经济数据,金额示例统一使用订单头字段 total_amount

Table Primary grain主粒度 Important columns关键列 Relationship关系
customers One row per customer每位客户一行 customer_id, customer_name, region, created_at Parent of ordersorders 的父表
orders One row per order每张订单一行 order_id, customer_id, order_date, status, total_amount Many orders per customer每位客户可有多张订单
order_items One row per order-product line每个订单商品行一行 order_id, product_id, quantity, unit_price Many lines per order每张订单可有多个商品行
products One row per product每件商品一行 product_id, product_name, category Parent of order itemsorder_items 的父表
payments One row per payment event每次付款事件一行 payment_id, order_id, paid_at, amount, payment_status Zero or many events per order每张订单可有零到多个事件
Relationship map关系图
customers 1 ─── * orders 1 ─── * order_items * ─── 1 products
                         │
                         └──────── * payments

Canonical reporting amount: orders.total_amount
Canonical completed-order rule: orders.status = 'completed'
Half-open date interval: date >= start AND date < next_period_start

The model deliberately exposes a common trap: joining orders to both order_items and payments can multiply rows. If an order has three item lines and two payment events, the combined join can produce six rows before aggregation. Decide the measure's source and pre-aggregate each one-to-many branch before combining it.

该模型刻意保留了一个常见陷阱:同时把 orders 连接到 order_itemspayments 可能造成行乘法。如果一张订单有三个商品行和两个付款事件,聚合前的组合连接可能产生六行。必须先决定指标来自哪张表,并在合并前分别预聚合每个一对多分支。

Read every SQL example as a six-part analytical contract把每个 SQL 示例视为六部分分析契约

A natural-language question hides choices that SQL must make explicit. Before looking at the code, identify the measure, population, time boundary, grouping dimensions, row grain, and tie or null behavior. After looking at the code, verify that those choices survived translation.

自然语言问题隐藏着许多必须在 SQL 中显式化的选择。阅读代码前,先识别指标、总体、时间边界、分组维度、行粒度,以及并列值或 NULL 的处理方式;阅读代码后,再验证这些选择是否在翻译过程中被保留下来。

1. Business question1. 业务问题

What decision or observation should the result support?

结果要支持什么决策或观察?

2. Metric definition2. 指标定义

Which field, status rule, unit, and aggregation define the measure?

哪个字段、状态规则、单位和聚合共同定义指标?

3. Population and time3. 总体与时间

Which entities qualify, and are date boundaries inclusive or exclusive?

哪些实体符合条件,日期边界是包含还是排除?

4. Result grain4. 结果粒度

Does one row represent an order, customer, region-month, or ranked entity?

一行表示订单、客户、地区月份还是排名实体?

5. SQL pattern5. SQL 模式

Which filters, joins, aggregates, CTEs, or windows implement the contract?

哪些筛选、连接、聚合、CTE 或窗口实现了契约?

6. Verification6. 验证

Which row-count, total, uniqueness, null, and edge-case checks could falsify the answer?

哪些行数、总额、唯一性、NULL 和边界检查可以证伪结果?

The examples use named placeholders such as :start_date. These are conceptual parameters, not a universal wire format. Bind them through the parameter mechanism of your driver, warehouse, BI tool, or orchestration layer. Never substitute untrusted values by concatenating strings.

示例使用 :start_date 这类命名占位符。它们表示概念参数,并不是所有系统通用的传输格式。请通过数据库驱动、数据仓库、BI 工具或编排层提供的参数机制绑定值,绝不能通过字符串拼接插入不可信输入。

SQL query example 1: filter completed orders and sort deterministicallySQL 查询示例1:筛选已完成订单并进行确定性排序

Business question: “List completed orders placed in April 2026, newest first.” The result grain is one row per order. A precise prompt should name the status, start date, exclusive next-period boundary, selected columns, and a stable secondary sort key.

业务问题:“列出 2026 年 4 月完成的订单,最新订单排在前面。”结果粒度为每张订单一行。精确提示应说明状态、开始日期、下期排除边界、所需列,以及稳定的第二排序键。

PostgreSQL-style queryPostgreSQL 风格查询
SELECT
  o.order_id,
  o.customer_id,
  o.order_date,
  o.total_amount
FROM orders AS o
WHERE o.status = 'completed'
  AND o.order_date >= DATE '2026-04-01'
  AND o.order_date <  DATE '2026-05-01'
ORDER BY
  o.order_date DESC,
  o.order_id DESC;

Why this shape: a half-open interval includes every timestamp on April 30 without relying on an assumed last second of the day. The secondary order_id sort makes output deterministic when multiple orders share the same timestamp. Selecting named columns also protects downstream consumers from silent column-order changes.

为什么这样写:半开区间能包含 4 月 30 日的所有时间戳,而不需要猜测当天“最后一秒”。当多张订单时间相同时,第二排序键 order_id 让输出保持确定。显式选择列还能避免上游增加字段后,下游因列顺序变化而悄然出错。

Verify:验证: confirm every row is completed, minimum and maximum timestamps stay inside the interval, and COUNT(*) = COUNT(DISTINCT order_id). Test midnight, month-end, and timezone conversion explicitly.确认每行状态均为 completed,最小与最大时间戳都在区间内,并验证 COUNT(*) = COUNT(DISTINCT order_id)。还要显式测试午夜、月末和时区转换。

SQL query example 2: calculate monthly orders, revenue, and average order valueSQL 查询示例2:计算月度订单数、收入与平均订单金额

Business question: “For each month in 2026, show completed-order count, completed revenue, and average order value.” The result grain is one row per calendar month. Revenue and average order value both come from the one-row-per-order table, so the query must not join item or payment detail.

业务问题:“按 2026 年每个月展示已完成订单数、已完成收入和平均订单金额。”结果粒度为每个自然月一行。收入与平均订单金额都来自每订单一行的 orders 表,因此查询不应连接商品行或付款明细。

Monthly aggregation月度聚合
SELECT
  DATE_TRUNC('month', o.order_date) AS order_month,
  COUNT(*)                           AS completed_orders,
  SUM(o.total_amount)               AS completed_revenue,
  AVG(o.total_amount)               AS average_order_value
FROM orders AS o
WHERE o.status = 'completed'
  AND o.order_date >= DATE '2026-01-01'
  AND o.order_date <  DATE '2027-01-01'
GROUP BY DATE_TRUNC('month', o.order_date)
ORDER BY order_month;

Interpretation: this returns only months that contain at least one completed order. If the report must show zero-activity months, join the aggregation to an approved calendar table or generated date series. Do not fill gaps in the presentation layer without documenting that behavior, because a missing month and a true zero are different observations.

解释:该查询只返回至少有一张已完成订单的月份。如果报表必须显示零活动月份,应把聚合结果连接到批准的日历表或日期序列。不要在展示层悄悄补零,因为“缺失月份”和“真实为零”代表不同观测。

Verify:验证: the sum of monthly order counts must equal the independently filtered annual order count; monthly revenue must reconcile to the same order population; average order value should equal revenue divided by order count, subject to the system's decimal and rounding policy.月度订单数之和应等于独立筛选得到的年度订单数;月度收入应与同一订单总体核对;平均订单金额应等于收入除以订单数,并遵循系统的小数与舍入政策。

SQL query example 3: find top customers with a controlled joinSQL 查询示例3:通过受控连接找出高价值客户

Business question: “Show the ten customers with the highest completed-order revenue in Q1 2026, including region and order count.” The result grain is one row per customer. The customer table provides descriptive attributes; the order table provides the count and amount.

业务问题:“展示 2026 年第一季度已完成订单收入最高的十位客户,并包含地区和订单数。”结果粒度为每位客户一行。customers 表提供描述属性,orders 表提供订单数与金额。

Top customers by revenue按收入排名客户
SELECT
  c.customer_id,
  c.customer_name,
  c.region,
  COUNT(*)             AS completed_orders,
  SUM(o.total_amount)  AS completed_revenue
FROM customers AS c
JOIN orders AS o
  ON o.customer_id = c.customer_id
WHERE o.status = 'completed'
  AND o.order_date >= DATE '2026-01-01'
  AND o.order_date <  DATE '2026-04-01'
GROUP BY
  c.customer_id,
  c.customer_name,
  c.region
ORDER BY
  completed_revenue DESC,
  c.customer_id
FETCH FIRST 10 ROWS ONLY;

Why this shape: the join remains one customer to many orders, and aggregation returns to one customer per row. customer_id is included in grouping even if names appear unique; names can change or collide. The final customer ID ordering resolves revenue ties deterministically. In MySQL or PostgreSQL, LIMIT 10 is a common alternative to the standard-style fetch clause.

为什么这样写:连接保持“一位客户对应多张订单”,聚合后回到“每位客户一行”。即使客户名看似唯一,也要按 customer_id 分组,因为名称可能变更或重复。最终以客户 ID 处理收入并列,让结果确定。在 MySQL 或 PostgreSQL 中,常见替代写法是 LIMIT 10

Verify:验证: compare the sum of all customer aggregates—not only the top ten—with the Q1 completed-order control total. Check that each order contributes once, inspect ties at rank ten, and confirm whether refunded or partially settled orders should remain in the governed completed-order definition.把全部客户聚合值(而不只是前十名)与第一季度已完成订单控制总额核对。检查每张订单是否只贡献一次,检查第十名附近的并列情况,并确认退款或部分结算订单是否仍属于治理后的“已完成订单”定义。

SQL query example 4: keep customers with zero orders using LEFT JOINSQL 查询示例4:使用 LEFT JOIN 保留零订单客户

Business question: “For every customer created before 2026, show the number and value of completed orders in Q1 2026, including customers with none.” The result grain is one row per eligible customer. The date and status predicates belong in the join condition so they limit matching orders without removing unmatched customers.

业务问题:“针对 2026 年前创建的每位客户,展示 2026 年第一季度已完成订单数量与金额,包括没有订单的客户。”结果粒度为每位符合条件的客户一行。日期与状态条件应放在连接条件中,这样只限制匹配订单,而不会删除未匹配客户。

Zero-preserving customer summary保留零值的客户汇总
SELECT
  c.customer_id,
  c.customer_name,
  COUNT(o.order_id)                    AS completed_orders,
  COALESCE(SUM(o.total_amount), 0)     AS completed_revenue
FROM customers AS c
LEFT JOIN orders AS o
  ON o.customer_id = c.customer_id
 AND o.status = 'completed'
 AND o.order_date >= DATE '2026-01-01'
 AND o.order_date <  DATE '2026-04-01'
WHERE c.created_at < DATE '2026-01-01'
GROUP BY
  c.customer_id,
  c.customer_name
ORDER BY c.customer_id;

Critical details: use COUNT(o.order_id), not COUNT(*). An unmatched customer still produces one null-extended row, so COUNT(*) would incorrectly report one order. SUM over no matches returns null and is intentionally converted to zero. Moving the order predicates into WHERE would reject null-extended rows and turn the outer join into an effective inner join.

关键细节:应使用 COUNT(o.order_id),不能使用 COUNT(*)。未匹配客户仍会产生一条右侧补 NULL 的行,因此 COUNT(*) 会错误报告一张订单。无匹配时 SUM 返回 NULL,这里有意转为零。如果把订单条件移到 WHERE,补 NULL 的行会被拒绝,外连接实际上就变成了内连接。

Verify:验证: the output row count should equal the eligible-customer count; customers with no matching orders must show zero for both measures; the sum of customer order counts and revenue must reconcile to the independent Q1 completed-order totals for the eligible customer population.输出行数应等于符合条件的客户数;没有匹配订单的客户两个指标都应为零;客户订单数与收入之和应与该客户总体的第一季度已完成订单独立总额核对。

SQL query example 5: compare order statuses with conditional aggregationSQL 查询示例5:使用条件聚合比较订单状态

Business question: “By region, compare completed, cancelled, and pending order counts in Q1 2026, and calculate the completed share of all orders.” The result grain is one row per region. One scan can produce several governed counts, but the numerator and denominator must use compatible populations.

业务问题:“按地区比较 2026 年第一季度已完成、已取消和待处理订单数,并计算已完成订单占全部订单的比例。”结果粒度为每个地区一行。一次扫描可以生成多个治理后的计数,但分子与分母必须使用相容总体。

Status mix by region按地区统计状态构成
SELECT
  c.region,
  COUNT(*) FILTER (WHERE o.status = 'completed') AS completed_orders,
  COUNT(*) FILTER (WHERE o.status = 'cancelled') AS cancelled_orders,
  COUNT(*) FILTER (WHERE o.status = 'pending')   AS pending_orders,
  COUNT(*)                                        AS all_orders,
  ROUND(
    COUNT(*) FILTER (WHERE o.status = 'completed')::numeric
    / NULLIF(COUNT(*), 0),
    4
  ) AS completed_share
FROM orders AS o
JOIN customers AS c
  ON c.customer_id = o.customer_id
WHERE o.order_date >= DATE '2026-01-01'
  AND o.order_date <  DATE '2026-04-01'
GROUP BY c.region
ORDER BY c.region;

Dialect note: PostgreSQL supports aggregate FILTER. A portable alternative is SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END). BigQuery supports COUNTIF. MySQL users commonly use conditional SUM. The business definition must remain identical even when syntax changes.

方言说明:PostgreSQL 支持聚合 FILTER。更通用的替代方式是 SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END);BigQuery 支持 COUNTIF;MySQL 常用条件 SUM。语法可以变化,但业务定义必须保持一致。

The denominator here includes every Q1 order, including statuses not displayed as separate columns. If the business wants completed share among only completed, cancelled, and pending orders, restrict both numerator and denominator to that set. Label the metric accordingly; “completion rate” is not self-defining.

这里的分母包含第一季度所有订单,包括未单独展示的其他状态。如果业务要求“已完成、已取消、待处理三类中的完成占比”,就要同时把分子与分母限制在该集合内。指标名称也必须对应定义;“完成率”本身并不能说明总体。

Verify:验证: the displayed status counts should never exceed all orders, regional all-order counts should sum to the Q1 control count, completed share must stay between zero and one, and unmapped or null statuses should be quantified rather than silently discarded.展示的各状态数不得超过全部订单数;各地区全部订单数之和应等于第一季度控制总数;完成占比应在0到1之间;未映射或 NULL 状态必须量化,不能悄然丢弃。

SQL query example 6: pre-aggregate one-to-many tables before joiningSQL 查询示例6:连接前先聚合一对多明细表

Business question: “For each completed order in April 2026, show order value, item quantity, successful payment amount, and the difference between paid and ordered value.” The result grain is one row per order. Both item lines and payment events are one-to-many children, so joining raw rows would create a many-to-many multiplication within each order.

业务问题:“针对 2026 年 4 月每张已完成订单,展示订单金额、商品数量、成功付款金额,以及已付金额与订单金额之间的差额。”结果粒度为每张订单一行。商品行和付款事件都是一对多子表,直接连接原始行会在订单内部形成多对多乘法。

Safe pre-aggregation pattern安全预聚合模式
WITH item_totals AS (
  SELECT
    oi.order_id,
    SUM(oi.quantity) AS item_quantity
  FROM order_items AS oi
  GROUP BY oi.order_id
),
payment_totals AS (
  SELECT
    p.order_id,
    SUM(p.amount) AS successful_payment_amount
  FROM payments AS p
  WHERE p.payment_status = 'succeeded'
  GROUP BY p.order_id
)
SELECT
  o.order_id,
  o.total_amount AS order_value,
  COALESCE(i.item_quantity, 0) AS item_quantity,
  COALESCE(p.successful_payment_amount, 0) AS paid_amount,
  COALESCE(p.successful_payment_amount, 0) - o.total_amount
    AS paid_minus_order_value
FROM orders AS o
LEFT JOIN item_totals AS i
  ON i.order_id = o.order_id
LEFT JOIN payment_totals AS p
  ON p.order_id = o.order_id
WHERE o.status = 'completed'
  AND o.order_date >= DATE '2026-04-01'
  AND o.order_date <  DATE '2026-05-01'
ORDER BY o.order_id;

Why this shape: each CTE restores one row per order before the branches are combined. The final joins therefore preserve order grain. The query does not assume that item-line value equals the order header or that successful payments always equal completed order value; instead, it exposes the reconciliation difference for investigation.

为什么这样写:每个 CTE 在分支合并前先恢复到“每张订单一行”,因此最终连接能够保留订单粒度。查询不会假设商品行金额必然等于订单头金额,也不会假设成功付款必然等于已完成订单金额,而是显式展示核对差额以供调查。

Verify:验证: the final row count and distinct order count must match; each child CTE must contain at most one row per order; investigate nonzero reconciliation differences using known refund, split-payment, rounding, tax, shipping, and timing rules before treating them as errors.最终行数与不同订单数必须相等;每个子 CTE 对每张订单最多只能有一行;对非零差额,应先结合退款、拆分付款、舍入、税费、运费和时点规则调查,再判断是否为错误。

SQL query example 7: find customers without recent completed ordersSQL 查询示例7:找出近期没有已完成订单的客户

Business question: “Find customers created before 2026 who had no completed order in the first half of 2026.” The result grain is one row per customer. This is an anti-semi-join: return an outer row only when no qualifying inner row exists.

业务问题:“找出 2026 年前创建、但在 2026 年上半年没有已完成订单的客户。”结果粒度为每位客户一行。这是反半连接:只有不存在符合条件的内部行时,才返回外部行。

NOT EXISTS anti-joinNOT EXISTS 反连接
SELECT
  c.customer_id,
  c.customer_name,
  c.region
FROM customers AS c
WHERE c.created_at < DATE '2026-01-01'
  AND NOT EXISTS (
    SELECT 1
    FROM orders AS o
    WHERE o.customer_id = c.customer_id
      AND o.status = 'completed'
      AND o.order_date >= DATE '2026-01-01'
      AND o.order_date <  DATE '2026-07-01'
  )
ORDER BY c.customer_id;

Why NOT EXISTS: it expresses absence directly and avoids the null semantics that can make NOT IN surprising when the subquery contains null. A left join followed by WHERE o.order_id IS NULL can also work, but the qualifying predicates must stay in the join condition. NOT EXISTS makes the intended anti-match boundary easier to audit.

为什么使用 NOT EXISTS它直接表达“不存在”,并避免子查询包含 NULL 时 NOT IN 可能出现的意外三值逻辑。LEFT JOIN 后使用 WHERE o.order_id IS NULL 也可以实现,但符合条件的谓词必须留在连接条件中。NOT EXISTS 更容易审查反匹配边界。

Do not label these customers “churned” unless the organization has a governed churn definition. The query proves only that no qualifying completed order exists in the selected interval. A new, dormant, seasonal, blocked, refunded, or externally served customer may require a different business classification.

除非组织已经治理了流失定义,否则不要把这些客户直接标记为“流失”。该查询只能证明选定区间内不存在符合条件的已完成订单。新客户、休眠客户、季节性客户、受限客户、退款客户或通过其他渠道服务的客户可能需要不同业务分类。

Verify:验证: sample returned customers and prove that the inner query returns zero rows; sample excluded customers and locate at least one qualifying order; test customers with only cancelled, pending, refunded, boundary-date, or null-status orders.抽样返回客户并证明内部查询返回零行;抽样被排除客户并找到至少一张符合条件的订单;测试只有已取消、待处理、已退款、边界日期或 NULL 状态订单的客户。

SQL query example 8: rank the top three products within each categorySQL 查询示例8:在每个类别内排名前三商品

Business question: “For completed orders in Q2 2026, return the three products with the highest item revenue in each category.” The output grain is one row per category-product. First aggregate order-item revenue at that grain, then rank the aggregated rows inside each category.

业务问题:“针对 2026 年第二季度已完成订单,返回每个类别中商品行收入最高的三件商品。”输出粒度为每个“类别—商品”一行。先在该粒度聚合订单商品收入,再在每个类别内部对聚合行排名。

Top three products per category每个类别前三商品
WITH product_revenue AS (
  SELECT
    p.category,
    p.product_id,
    p.product_name,
    SUM(oi.quantity * oi.unit_price) AS item_revenue
  FROM orders AS o
  JOIN order_items AS oi
    ON oi.order_id = o.order_id
  JOIN products AS p
    ON p.product_id = oi.product_id
  WHERE o.status = 'completed'
    AND o.order_date >= DATE '2026-04-01'
    AND o.order_date <  DATE '2026-07-01'
  GROUP BY
    p.category,
    p.product_id,
    p.product_name
),
ranked_products AS (
  SELECT
    pr.*,
    ROW_NUMBER() OVER (
      PARTITION BY pr.category
      ORDER BY pr.item_revenue DESC, pr.product_id
    ) AS category_position
  FROM product_revenue AS pr
)
SELECT
  category,
  product_id,
  product_name,
  item_revenue,
  category_position
FROM ranked_products
WHERE category_position <= 3
ORDER BY category, category_position;

Tie decision: ROW_NUMBER returns exactly three rows per category when at least three products exist; product ID breaks equal-revenue ties. Use RANK when tied products should share a rank and the output may exceed three rows. Use DENSE_RANK when ranks should not have gaps. The prompt must state which interpretation the decision requires.

并列决策:当类别至少有三件商品时,ROW_NUMBER 恰好返回三行;商品 ID 用于打破收入并列。如果并列商品应共享名次、且输出可以超过三行,则使用 RANK;如果排名不应跳号,则使用 DENSE_RANK。提示必须说明决策需要哪种解释。

PostgreSQL evaluates window functions after WHERE, grouping, and ordinary aggregation, so the ranking is calculated in a separate query level and filtered outside it. BigQuery can express the last step with QUALIFY; that is a dialect feature, not portable standard syntax.

PostgreSQL 在 WHERE、分组和普通聚合之后计算窗口函数,因此排名需要在单独查询层中生成,再由外层筛选。BigQuery 可以用 QUALIFY 表达最后一步,但这是方言特性,不是可移植标准语法。

Verify:验证: reconcile the unfiltered product totals to item-level Q2 revenue, confirm no category has more than three rows under the chosen tie rule, inspect categories with fewer than three products, and compare item revenue with order-header revenue only after accounting for tax, shipping, discounts, and rounding.把未筛选的商品总额与第二季度商品行收入核对;在选定并列规则下确认每个类别不超过三行;检查商品不足三件的类别;只有在考虑税费、运费、折扣和舍入后,才能把商品行收入与订单头收入比较。

SQL query example 9: calculate monthly revenue, running total, and changeSQL 查询示例9:计算月度收入、累计值与环比变化

Business question: “For completed orders in 2026, show monthly revenue, cumulative year-to-date revenue, the prior month's revenue, and month-over-month change.” The result grain is one row per observed month. Aggregate first; apply windows second.

业务问题:“针对 2026 年已完成订单,展示月度收入、年内累计收入、上月收入和环比变化。”结果粒度为每个有观测值的月份一行。先聚合,再应用窗口函数。

Monthly time-series windows月度时间序列窗口
WITH monthly_revenue AS (
  SELECT
    DATE_TRUNC('month', o.order_date) AS revenue_month,
    SUM(o.total_amount)               AS revenue
  FROM orders AS o
  WHERE o.status = 'completed'
    AND o.order_date >= DATE '2026-01-01'
    AND o.order_date <  DATE '2027-01-01'
  GROUP BY DATE_TRUNC('month', o.order_date)
),
with_prior AS (
  SELECT
    mr.revenue_month,
    mr.revenue,
    SUM(mr.revenue) OVER (
      ORDER BY mr.revenue_month
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS year_to_date_revenue,
    LAG(mr.revenue) OVER (
      ORDER BY mr.revenue_month
    ) AS prior_month_revenue
  FROM monthly_revenue AS mr
)
SELECT
  revenue_month,
  revenue,
  year_to_date_revenue,
  prior_month_revenue,
  revenue - prior_month_revenue AS absolute_change,
  ROUND(
    (revenue - prior_month_revenue)
    / NULLIF(prior_month_revenue, 0),
    4
  ) AS change_rate
FROM with_prior
ORDER BY revenue_month;

Missing-month warning: LAG means prior returned row, not necessarily prior calendar month. If February has no row, April's prior returned row may be January or March depending on the data. For calendar-continuous analysis, join monthly totals to a calendar series first and choose whether missing activity means zero, unknown, or not applicable.

缺失月份警告:LAG 表示前一条返回行,并不必然表示前一个自然月。如果二月没有行,四月的前一行可能是三月,也可能因数据缺口而更早。进行连续日历分析时,应先把月度总额连接到日历序列,并明确缺失活动表示零、未知还是不适用。

The explicit ROWS frame makes the running-total rule visible. With non-unique ordering values, the default frame can include peers in ways that surprise reviewers. A month is unique in this CTE, but the explicit frame remains useful documentation.

显式 ROWS 窗口框架让累计规则清晰可见。当排序值不唯一时,默认框架可能把并列行一起纳入,导致审查者误解。本 CTE 中月份是唯一的,但显式框架仍然是有价值的文档。

Verify:验证: the final running total must equal independently calculated annual revenue; the first prior-month value should be null; test zero and missing prior months; confirm the window order is chronological and month fields use the intended reporting timezone.最终累计值必须等于独立计算的年度收入;第一个上月值应为 NULL;测试上月为零和缺失的情况;确认窗口顺序为时间顺序,月份字段采用预期报表时区。

SQL query example 10: return each customer's latest completed orderSQL 查询示例10:返回每位客户最新的已完成订单

Business question: “For every customer who has a completed order, return the latest completed order and its value.” The result grain is one row per customer with qualifying history. The phrase “latest” requires a deterministic rule when timestamps tie.

业务问题:“针对每位有已完成订单的客户,返回其最新已完成订单及金额。”结果粒度为每位有符合条件历史的客户一行。“最新”在时间戳并列时必须有确定规则。

Latest completed order per customer每位客户最新已完成订单
WITH ranked_orders AS (
  SELECT
    o.customer_id,
    o.order_id,
    o.order_date,
    o.total_amount,
    ROW_NUMBER() OVER (
      PARTITION BY o.customer_id
      ORDER BY o.order_date DESC, o.order_id DESC
    ) AS recency_position
  FROM orders AS o
  WHERE o.status = 'completed'
)
SELECT
  c.customer_id,
  c.customer_name,
  r.order_id,
  r.order_date,
  r.total_amount
FROM ranked_orders AS r
JOIN customers AS c
  ON c.customer_id = r.customer_id
WHERE r.recency_position = 1
ORDER BY c.customer_id;

Why not MAX(order_date) alone: the maximum timestamp identifies a value, not necessarily the rest of the row. Joining the maximum back can return multiple orders when timestamps tie. ROW_NUMBER keeps the complete row and applies an explicit tie-breaker. PostgreSQL's DISTINCT ON can solve the same task compactly, but it is PostgreSQL-specific.

为什么不能只用 MAX(order_date)最大时间戳只识别一个值,并不能唯一确定该行其他字段。把最大值连接回原表,在时间并列时可能返回多张订单。ROW_NUMBER 保留完整行,并应用明确并列规则。PostgreSQL 的 DISTINCT ON 也能简洁解决该任务,但属于 PostgreSQL 特有语法。

This query excludes customers without a completed order. If the requirement says “every customer,” start from customers and left join the ranked result, then describe null order fields as no qualifying history rather than missing data.

该查询排除了没有已完成订单的客户。如果需求写的是“每位客户”,就应从 customers 出发,LEFT JOIN 排名结果,并把 NULL 订单字段解释为“没有符合条件的历史”,而不是笼统称为缺失数据。

Verify:验证: customer IDs must be unique in the output; no later completed order may exist for a returned customer; test tied timestamps and customers with only non-completed orders; confirm the tie-breaker reflects the business's event ordering.输出中的客户 ID 必须唯一;每位返回客户都不应存在更晚的已完成订单;测试时间戳并列和只有非完成订单的客户;确认并列规则符合业务事件顺序。

SQL query example 11: calculate category revenue and share of totalSQL 查询示例11:计算类别收入及总体占比

Business question: “For completed Q2 2026 orders, show item revenue by product category and each category's share of item revenue.” The result grain is one row per category. First calculate category totals, then apply a window aggregate across those totals.

业务问题:“针对 2026 年第二季度已完成订单,展示按商品类别计算的商品行收入,以及各类别占商品行总收入的比例。”结果粒度为每个类别一行。先计算类别总额,再对这些总额应用窗口聚合。

Category share of item revenue商品行收入类别占比
WITH category_revenue AS (
  SELECT
    p.category,
    SUM(oi.quantity * oi.unit_price) AS item_revenue
  FROM orders AS o
  JOIN order_items AS oi
    ON oi.order_id = o.order_id
  JOIN products AS p
    ON p.product_id = oi.product_id
  WHERE o.status = 'completed'
    AND o.order_date >= DATE '2026-04-01'
    AND o.order_date <  DATE '2026-07-01'
  GROUP BY p.category
)
SELECT
  category,
  item_revenue,
  ROUND(
    item_revenue
    / NULLIF(SUM(item_revenue) OVER (), 0),
    4
  ) AS revenue_share
FROM category_revenue
ORDER BY item_revenue DESC, category;

Measure boundary: this computes item-line revenue from quantity times unit price. It is not automatically equal to recognized revenue, paid cash, or the order header. Discounts, returns, tax, shipping, currency conversion, allocation, and accounting recognition can create legitimate differences. Name the measure “item revenue” unless a governed transformation makes it something else.

指标边界:这里通过数量乘单价计算商品行收入。它不会自动等于确认收入、已收现金或订单头金额;折扣、退货、税费、运费、汇率转换、分摊和会计确认都可能造成合理差异。除非经过治理转换,否则应把该指标明确称为“商品行收入”。

A window aggregate avoids a self-join to the grand total. The empty OVER () means every category row participates in one window. The null-safe denominator prevents division by zero if the selected population has no item revenue.

窗口聚合避免了把类别结果再连接到总体总额。空的 OVER () 表示所有类别行共同参与一个窗口;分母使用 NULL 安全处理,以防选定总体没有商品行收入时除零。

Verify:验证: shares should sum to approximately one after rounding; category totals should reconcile to an independent item-level total; quantify null or unmapped categories; investigate negative quantities or values under the organization's returns policy.舍入后各占比之和应约等于1;类别总额应与独立商品行总额核对;量化 NULL 或未映射类别;根据组织退货政策调查负数量或负金额。

SQL query example 12: measure 30-day repeat purchase by first-order monthSQL 查询示例12:按首单月份衡量30天复购

Business question: “Group customers by their first completed-order month in 2026 and report how many placed another completed order within 30 days after the first order.” The output grain is one row per first-order month. The analysis requires a first event, a forward-looking event window, a customer-level flag, and a cohort aggregation.

业务问题:“按客户在 2026 年的首次已完成订单月份分组,报告其中有多少客户在首单后30天内再次完成订单。”输出粒度为每个首单月份一行。分析需要确定首次事件、后续事件窗口、客户级标记,再进行队列聚合。

Thirty-day repeat purchase cohort30天复购队列
WITH completed_orders AS (
  SELECT
    o.customer_id,
    o.order_id,
    o.order_date
  FROM orders AS o
  WHERE o.status = 'completed'
),
first_orders AS (
  SELECT
    co.customer_id,
    MIN(co.order_date) AS first_order_date
  FROM completed_orders AS co
  GROUP BY co.customer_id
),
eligible_first_orders AS (
  SELECT
    f.customer_id,
    f.first_order_date
  FROM first_orders AS f
  WHERE f.first_order_date >= DATE '2026-01-01'
    AND f.first_order_date <  DATE '2027-01-01'
    AND f.first_order_date
        <= CAST(:as_of_date AS timestamp) - INTERVAL '30 days'
),
customer_repeat_flags AS (
  SELECT
    e.customer_id,
    e.first_order_date,
    CASE WHEN EXISTS (
      SELECT 1
      FROM completed_orders AS later
      WHERE later.customer_id = e.customer_id
        AND later.order_date > e.first_order_date
        AND later.order_date <= e.first_order_date + INTERVAL '30 days'
    ) THEN 1 ELSE 0 END AS repeated_within_30_days
  FROM eligible_first_orders AS e
)
SELECT
  DATE_TRUNC('month', first_order_date) AS first_order_month,
  COUNT(*)                              AS new_customers,
  SUM(repeated_within_30_days)          AS repeat_customers_30d,
  ROUND(
    AVG(repeated_within_30_days::numeric),
    4
  ) AS repeat_rate_30d
FROM customer_repeat_flags
GROUP BY DATE_TRUNC('month', first_order_date)
ORDER BY first_order_month;

Censoring rule: a customer whose first order occurred near the data extract's end may not have a complete 30-day observation window. The :as_of_date condition includes only first orders with a mature observation window. If the report must show incomplete cohorts, label and separate them; otherwise recent cohorts will be biased downward.

删失规则:如果客户首单接近数据提取结束日期,就可能没有完整30天观察窗口。查询中的 :as_of_date 条件只纳入观察窗口已经成熟的首单。如果报表必须展示未成熟队列,应明确标记并单独呈现,否则近期队列会出现向下偏差。

Definition choices: decide whether the second order must be strictly later by timestamp, whether same-day separate orders count, whether refunded orders invalidate either event, which timezone defines a day, and whether the first completed order means lifetime first or first within 2026. This example uses lifetime first completed order and then selects cohorts whose first event occurred in 2026.

定义选择:必须决定第二张订单是否必须在时间戳上严格晚于首单、同日独立订单是否计入、退款是否使任一事件失效、一天由哪个时区定义,以及“首次已完成订单”是生命周期首单还是 2026 年内首单。本示例采用生命周期首次已完成订单,再选择首单发生在 2026 年的队列。

Verify:验证: each customer must appear once in the flag CTE; repeat customers cannot exceed new customers; inspect boundary events exactly 30 days later; apply the maturity cutoff; reproduce a small hand-checked cohort with known first and second orders.每位客户在标记 CTE 中只能出现一次;复购客户数不能超过新客户数;检查恰好30天后的边界事件;应用队列成熟截止条件;使用已知首单与复购订单的小样本手工复算。

Adapt the examples to the target SQL dialect before execution执行前先把示例适配到目标 SQL 方言

“SQL” is a language family implemented through product-specific dialects. A query can be logically sound and still fail because the target system uses different date functions, casts, identifier quoting, parameters, top-N syntax, or window filtering. Name the engine and version in the prompt whenever the output will be executed.

“SQL”是一组由不同产品方言实现的语言家族。查询逻辑可能正确,却因目标系统采用不同日期函数、类型转换、标识符引号、参数、Top-N 或窗口筛选语法而失败。只要输出将被执行,就应在提示中写明数据库引擎与版本。

Task任务 PostgreSQL MySQL 8.4 BigQuery / GoogleSQL Control控制点
Month bucket月份分桶 DATE_TRUNC('month', ts) DATE_FORMAT(ts, '%Y-%m-01') DATE_TRUNC(DATE(ts), MONTH) Return type and timezone differ返回类型与时区不同
Top rows前N行 LIMIT or FETCH LIMIT LIMIT Always pair with deterministic ordering必须搭配确定性排序
Conditional count条件计数 COUNT(*) FILTER SUM(CASE...) COUNTIF(...) Preserve identical population logic保持相同总体逻辑
Filter window result筛选窗口结果 Subquery or CTE子查询或 CTE Subquery or CTE子查询或 CTE QUALIFY Logical evaluation order still matters逻辑执行顺序仍然重要
Add 30 days增加30天 ts + INTERVAL '30 days' DATE_ADD(ts, INTERVAL 30 DAY) DATE_ADD(date, INTERVAL 30 DAY) Date versus timestamp semanticsDATE 与 TIMESTAMP 语义不同
Named parameter命名参数 Depends on driver, client, BI tool, or execution API取决于驱动、客户端、BI 工具或执行 API Bind values; do not concatenate绑定值,不要拼接

Treat the official PostgreSQL SQL tutorial and MySQL 8.4 SELECT reference as the authority for their respective dialects. Confirm behavior against the deployed version, because compatibility modes and feature releases can change accepted syntax.

应分别以官方 PostgreSQL SQL 教程MySQL 8.4 SELECT 参考作为各自方言的权威来源。还应针对实际部署版本确认行为,因为兼容模式和功能发布可能改变可接受语法。

Turn a vague data request into a testable natural-language SQL prompt把模糊数据请求改写为可测试的自然语言 SQL 提示

“Show sales by customer” is not a complete specification. It leaves sales meaning, customer population, time, status, currency, refund treatment, grouping grain, zero-activity behavior, sorting, and dialect unresolved. A generator must either guess or ask for clarification. A stronger prompt makes the decision boundary visible.

“按客户展示销售额”并不是完整规格。它没有解决销售额定义、客户总体、时间、状态、币种、退款处理、分组粒度、零活动行为、排序和方言。生成器只能猜测或追问。更强的提示会把决策边界显式化。

Prompt template提示模板
Engine and version:
Available tables, keys, and relevant columns:

Return [metric] for [population]
during [half-open date interval],
grouped at [one-row grain].

Include:
- [dimensions and measures]
- [status, null, refund, and zero-activity rules]
- [tie behavior and deterministic ordering]

Use bound parameters for [values].
Return read-only SQL only.
Do not invent tables, columns, relationships, or business definitions.
State unresolved assumptions before the SQL.
Vague phrase模糊表达 Clarification needed需要澄清 Example precise wording精确写法示例
“Sales”“销售额” Header, item, payment, recognized revenue, or net of refunds?订单头、商品行、付款、确认收入,还是扣除退款? “Sum completed orders.total_amount before refunds”“汇总退款前已完成订单的 total_amount”
“Last month”“上个月” Relative to which as-of date and timezone?相对于哪个截至日期和时区? “From 2026-06-01 inclusive to 2026-07-01 exclusive, UTC”“UTC下从2026-06-01含到2026-07-01不含”
“Top customers”“高价值客户” Top by what, how many, and how are ties handled?按什么指标、多少名、并列如何处理? “Exactly ten by completed revenue; break ties by customer_id”“按已完成收入取恰好10名;以 customer_id 打破并列”
“All customers”“所有客户” Include customers with no qualifying activity?是否包含没有符合条件活动的客户? “Preserve every eligible customer and return zero for no orders”“保留每位符合条件客户,无订单时返回零”
“Growth”“增长” Absolute, percent, compound, or contribution? What if prior value is zero?绝对值、百分比、复合还是贡献?上期为零怎么办? “Month-over-month percent change; return null when prior revenue is zero”“月度环比百分比;上月收入为零时返回 NULL”

Validate generated SQL in layers before trusting the answer在信任答案前分层验证生成的 SQL

SQL correctness has several layers. Parsing proves only that the target engine recognizes the syntax. Object resolution proves that tables and columns exist. Neither proves that joins, definitions, time boundaries, aggregation grain, or output meaning match the decision. Use a review sequence that can reject a plausible query early.

SQL 正确性包含多个层次。成功解析只证明目标引擎识别语法;对象解析只证明表和列存在;两者都不能证明连接、定义、时间边界、聚合粒度和输出含义符合决策。应使用能够尽早否定“看似合理查询”的审查顺序。

  1. Freeze the question and expected grain.冻结问题与预期粒度。 Write a one-sentence contract such as “one row per customer-month, completed orders only, UTC calendar months.” 写出一句话契约,例如“每个客户月份一行,仅含已完成订单,采用 UTC 自然月”。
  2. Parse in the target dialect.在目标方言中解析。 Use the actual engine or its official parser; do not infer portability from visual similarity. 使用真实引擎或官方解析器,不要根据视觉相似度推断可移植性。
  3. Resolve every object.解析每个对象。 Confirm schema qualification, table names, columns, aliases, data types, keys, and relationship direction. 确认 Schema 限定、表名、列、别名、数据类型、键和关系方向。
  4. Audit population and time.审查总体与时间。 Check status rules, exclusions, null behavior, timezone, inclusivity, and late-arriving or future records. 检查状态规则、排除条件、NULL 行为、时区、边界包含方式,以及迟到或未来记录。
  5. Audit join cardinality.审查连接基数。 Compare row counts before and after each join, measure key uniqueness, and pre-aggregate one-to-many branches. 比较每次连接前后的行数,测量键唯一性,并预聚合一对多分支。
  6. Reconcile measures independently.独立核对指标。 Compare counts and totals with a simpler trusted query, ledger, approved dashboard, or hand-checked sample. 把计数与总额同更简单的可信查询、台账、批准报表或手工样本核对。
  7. Test adversarial edge cases.测试对抗性边界案例。 Include nulls, duplicates, ties, zero denominators, empty periods, month-end timestamps, refunds, and multiple child rows. 包含 NULL、重复、并列、零分母、空期间、月末时间戳、退款和多个子行。
  8. Inspect the execution plan safely.安全检查执行计划。 Start with non-executing plan inspection where available; remember that EXPLAIN ANALYZE actually runs the statement. 在可用时先使用不执行的计划检查;记住 EXPLAIN ANALYZE 会真正执行语句。
  9. Run with constrained access.使用受限权限运行。 Use read-only, least-privilege credentials, bounded resources, and approved data environments. 使用只读、最小权限凭据、受限资源和批准的数据环境。
  10. Record evidence and ownership.记录证据与责任人。 Preserve the prompt, SQL, schema version, parameters, reviewer, test results, and known limitations. 保存提示、SQL、Schema 版本、参数、审查者、测试结果和已知限制。

PostgreSQL's official Using EXPLAIN documentation explains that a query plan contains scan, join, aggregate, and sort nodes, and warns that EXPLAIN ANALYZE actually executes the statement. For data-changing SQL, use an approved safe method rather than assuming the word “explain” prevents side effects.

PostgreSQL 官方 Using EXPLAIN 文档说明,查询计划由扫描、连接、聚合和排序等节点构成,并明确警告 EXPLAIN ANALYZE 会真正执行语句。对于会修改数据的 SQL,应采用批准的安全方法,不能因为命令中有“explain”就假设没有副作用。

Keep natural-language SQL generation separate from safe execution把自然语言 SQL 生成与安全执行分开

A generated statement is code. It must pass the same security and governance gates as hand-written SQL. Values such as customer IDs and date limits should be bound through prepared or parameterized interfaces. Table names, column names, sort directions, and other structural elements generally cannot be bound as values; when dynamic structure is necessary, select from a strict allow-list controlled by the application.

生成的语句仍然是代码,必须通过与手写 SQL 相同的安全和治理门槛。客户 ID、日期边界等值应通过预编译或参数化接口绑定。表名、列名、排序方向等结构元素通常不能作为值绑定;如果确实需要动态结构,应由应用从严格白名单中选择。

Values

Bind dates, IDs, statuses, thresholds, and search strings using the execution client's parameter API.

通过执行客户端的参数 API 绑定日期、ID、状态、阈值和搜索字符串。

Identifiers标识符

Map approved user choices to known table, column, and ordering identifiers; reject everything else.

把批准的用户选择映射到已知表、列和排序标识符,并拒绝其他输入。

Privileges权限

Use a read-only role limited to necessary schemas, views, rows, and columns; separate generation from execution approval.

使用仅能访问必要 Schema、视图、行与列的只读角色,并把生成与执行审批分开。

Resources资源

Apply statement timeouts, scan or cost limits, row limits where appropriate, cancellation, and workload isolation.

应用语句超时、扫描或成本限制、适当的行数限制、取消机制和工作负载隔离。

The OWASP SQL Injection Prevention Cheat Sheet recommends prepared statements with parameterized queries as a primary defense and discourages dynamic query construction through string concatenation. It also emphasizes least privilege as an additional control. Parameterization does not prove analytical correctness, but it prevents data values from rewriting intended SQL structure when implemented properly.

OWASP SQL 注入防护速查表把预编译语句与参数化查询列为主要防御,并反对通过字符串拼接构造动态查询;同时强调最小权限作为额外控制。参数化不能证明分析逻辑正确,但正确实现时可以防止数据值改写预期 SQL 结构。

Use the NL2SQL Query Tester to inspect a generated SQL pattern使用 NL2SQL Query Tester 检查生成的 SQL 模式

The InfiniSynapse NL2SQL Query Tester accepts a plain-English question and displays generated SQL over built-in synthetic examples. Its current page demonstrates table selection, join paths, filters, aggregates, ordering, and limits entirely in the browser. It is useful for inspecting how a question may be translated into SQL structure.

InfiniSynapse NL2SQL Query Tester 接受英文自然语言问题,并基于内置合成示例展示生成的 SQL。当前工具页在浏览器中演示表选择、连接路径、筛选、聚合、排序和限制,适合检查一个问题可能如何被翻译为 SQL 结构。

What the tester can demonstrate工具可以演示 What it does not establish工具不能证明 Your next control下一步控制
Question-to-SQL structure问题到 SQL 的结构 Correctness for your schema or business vocabulary对你的 Schema 或业务术语正确 Provide governed metadata and review every object提供治理元数据并审查每个对象
Illustrative joins, filters, and aggregates示例连接、筛选与聚合 Cardinality, data quality, or result accuracy on your data在你的数据上的基数、质量或结果准确性 Run row-count, uniqueness, reconciliation, and edge-case tests运行行数、唯一性、核对与边界测试
SQL text for review and adaptation供审查与适配的 SQL 文本 Execution, performance, permissions, or safe production behavior执行、性能、权限或生产安全行为 Parse, plan, parameterize, and execute in an approved environment在批准环境中解析、计划、参数化和执行

Test a precise business question against an illustrative NL2SQL workflow用示例 NL2SQL 流程测试一个精确业务问题

Start with the prompt contract above. Use synthetic names and values, inspect the generated SQL, then adapt and validate it against your approved schema before any real execution.

先使用上面的提示契约。输入合成名称与数值,检查生成 SQL;在任何真实执行前,再针对批准的 Schema 进行适配与验证。

Open the NL2SQL Query Tester打开 NL2SQL Query Tester Browser-based demonstration using built-in synthetic examples. It does not execute SQL or connect to your database.基于浏览器和内置合成示例的演示;不会执行 SQL,也不会连接你的数据库。

Follow a review-ready workflow from question to approved result执行从问题到批准结果的可审查工作流

  1. Name the decision.说明决策。 Identify the owner, action, deadline, and consequence the analysis will support. 识别分析要支持的责任人、行动、截止时间与后果。
  2. Define the metric contract.定义指标契约。 Specify numerator, denominator, statuses, units, currency, exclusions, and recognition rules. 说明分子、分母、状态、单位、币种、排除条件和确认规则。
  3. Describe result grain.描述结果粒度。 State exactly what one output row represents and which keys should be unique. 明确一条输出行代表什么,以及哪些键应唯一。
  4. Provide governed schema context.提供治理后的 Schema 上下文。 Supply approved tables, columns, data types, keys, relationships, descriptions, and dialect. 提供批准的表、列、数据类型、键、关系、说明和方言。
  5. Write a precise prompt.编写精确提示。 Include population, dates, grouping, zero behavior, ties, output columns, and unresolved assumptions. 包含总体、日期、分组、零值行为、并列、输出列和未解决假设。
  6. Generate read-only SQL.生成只读 SQL。 Keep generation separate from execution and reject invented objects. 把生成与执行分开,并拒绝虚构对象。
  7. Review structure and semantics.审查结构与语义。 Inspect selected fields, joins, filters, aggregation, windows, nulls, and ordering against the contract. 对照契约检查字段、连接、筛选、聚合、窗口、NULL 与排序。
  8. Validate with controls.使用控制验证。 Run counts, uniqueness, totals, samples, boundaries, and adversarial cases. 运行计数、唯一性、总额、样本、边界和对抗案例检查。
  9. Inspect cost and plan.检查成本与计划。 Use the target engine's planning tools, production-scale statistics, and representative parameters. 使用目标引擎计划工具、生产规模统计和代表性参数。
  10. Approve, observe, and version.批准、观测与版本化。 Record reviewer evidence, query and schema versions, runtime safeguards, ownership, and change triggers. 记录审查证据、查询与 Schema 版本、运行保护、责任人和变更触发条件。

Avoid twelve mistakes that make SQL examples misleading避免让 SQL 示例产生误导的十二个错误

Undefined result grain结果粒度未定义

A query cannot be validated if reviewers do not know what one row represents.

如果审查者不知道一行代表什么,查询就无法验证。

Using SELECT *使用 SELECT *

It hides the data contract and can break downstream consumers when schemas change.

它隐藏数据契约,并可能在 Schema 变化时破坏下游。

Inclusive end timestamps包含结束时间戳

“Through 23:59:59” can miss higher-precision events; prefer a half-open next-period boundary.

“截至23:59:59”可能漏掉更高精度事件;优先使用下期半开边界。

Outer-join filters in WHERE外连接条件放在 WHERE

Right-side filters can remove null-extended rows and destroy zero-activity coverage.

右表条件会删除补 NULL 的行,破坏零活动覆盖。

Counting * after a LEFT JOINLEFT JOIN 后统计 *

An unmatched parent still has one output row; count a non-null child key.

未匹配父行仍有一条输出;应统计非空子键。

Joining multiple detail branches raw直接连接多个明细分支

Items times payments can multiply measures; pre-aggregate each branch to the target key.

商品行乘付款行会放大指标;应把每个分支预聚合到目标键。

Nondeterministic top-N不确定的 Top-N

A limit without complete ordering can change rows between executions.

没有完整排序的限制可能在不同执行间返回不同记录。

Ignoring tie semantics忽略并列语义

ROW_NUMBER, RANK, and DENSE_RANK answer different questions.

ROW_NUMBER、RANK 与 DENSE_RANK 回答不同问题。

Treating missing as zero把缺失当作零

A missing month may mean no events, incomplete ingestion, or excluded data.

缺失月份可能表示无事件、摄取不完整或数据被排除。

Unqualified business terms业务术语未限定

Revenue, active, customer, conversion, and churn need governed definitions.

收入、活跃、客户、转化和流失都需要治理定义。

String-concatenated inputs字符串拼接输入

Use parameter APIs for values and allow-lists for unavoidable dynamic identifiers.

值应使用参数 API,不可避免的动态标识符应使用白名单。

Optimizing before proving correctness正确性前先优化

First establish population, grain, joins, and reconciled totals; then improve the plan.

先确认总体、粒度、连接和核对总额,再优化执行计划。

Frequently asked questions about SQL query examplesSQL 查询实例常见问题

What is an SQL query example?什么是 SQL 查询实例?

An SQL query example connects a specific data question to required tables and columns, a complete SQL statement, the intended result grain, and verification checks.

SQL 查询实例是在明确上下文中展示数据问题、所需表与列、完整 SQL 语句、预期结果粒度及验证方法的完整案例。

What are the most common SQL queries?最常见的 SQL 查询有哪些?

Common analytical SQL filters and sorts rows, joins related tables, aggregates measures, finds missing relationships, ranks records within groups, and compares values across time.

常见分析 SQL 包括筛选与排序、连接相关表、按明确粒度聚合、查找缺失关系、组内排名以及跨时间比较。

How do I write a good Chinese prompt for SQL?如何为 SQL 编写高质量中文提示?

State the metric, population, date range, grouping dimensions, inclusion and exclusion rules, result grain, tie behavior, and target SQL dialect.

说明指标、总体、日期范围、分组维度、纳入和排除规则、结果行粒度、并列处理及目标 SQL 方言,并用受治理定义替代模糊业务术语。

Can these SQL examples run without changes?这些 SQL 实例可以不修改直接运行吗?

Usually not. Adapt the synthetic schema and PostgreSQL-style syntax to your actual tables, columns, data types, date functions, parameters, and database dialect.

通常不可以。示例使用合成 Schema 和 PostgreSQL 风格语法,需要根据实际数据库适配表名、字段、数据类型、日期函数、参数和方言。

How should I validate AI-generated SQL?应如何验证 AI 生成的 SQL?

Parse it in the target dialect, confirm referenced objects, join cardinality and result grain, reconcile trusted totals, test edge cases, inspect the plan, and use read-only least privilege.

在目标方言中解析,核对引用对象、连接基数和结果粒度,与可信总额进行核对,测试边界情况,审查执行计划,并在只读最小权限环境运行。

Does InfiniSynapse NL2SQL Query Tester execute SQL?InfiniSynapse NL2SQL Query Tester 会执行 SQL 吗?

No. It demonstrates natural-language-to-SQL structure with synthetic examples and does not connect to your database or execute generated SQL.

不会。它使用内置合成示例演示自然语言到 SQL 的转换,不连接用户数据库,也不能证明查询适用于用户自己的 Schema。

Primary references for SQL syntax, windows, plans, and safetySQL 语法、窗口、执行计划与安全的权威参考

  • PostgreSQL: The SQL Language — official tutorial covering querying, joins, and aggregate functions.——官方教程,涵盖查询、连接和聚合函数。
  • PostgreSQL: Window Functions — official definitions for ROW_NUMBER, RANK, DENSE_RANK, LAG, frames, and peer behavior.——ROW_NUMBER、RANK、DENSE_RANK、LAG、窗口框架和并列行为的官方定义。
  • PostgreSQL: Using EXPLAIN — official plan-reading guidance and the execution warning for EXPLAIN ANALYZE.——官方执行计划阅读指南,以及 EXPLAIN ANALYZE 会执行语句的警告。
  • MySQL 8.4: SELECT Statement — official MySQL syntax for SELECT, WITH, joins, grouping, windows, ordering, and limits.——MySQL 关于 SELECT、WITH、连接、分组、窗口、排序和限制的官方语法。
  • OWASP: SQL Injection Prevention Cheat Sheet — parameterization, allow-list validation, and least-privilege controls.——参数化、白名单验证与最小权限控制。
Editorial note:编辑说明: the schema, SQL, and verification scenarios on this page are original synthetic educational examples, not benchmark results or statements about a customer's production data. SQL features and vendor documentation can change; verify the current documentation and deployed engine version before implementation.本页 Schema、SQL 和验证场景均为原创合成教学示例,不是基准测试结果,也不代表任何客户生产数据。SQL 特性和厂商文档可能变化;实施前应核对最新文档与实际部署引擎版本。