From 054bbae4fbc9b5e45a3d201e7b9b927520488aeb Mon Sep 17 00:00:00 2001 From: ulleo Date: Mon, 21 Sep 2026 14:43:19 +0800 Subject: [PATCH] fix(chat): constrain SQL row-limit placement to outermost query in prompt templates (#1202) The row-limit policy in query_limit/no_query_limit did not specify WHERE the limit should be applied, so LLMs could put LIMIT/ROWNUM/TOP inside subqueries, truncating the data feeding aggregation (limiting accessed rows instead of the final result set). - query_limit/no_query_limit: limit must be applied only to the outermost query; never inside subqueries, derived tables or CTEs; add conditional per-group top-N note (window functions where supported) - process_check (template.yaml + Oracle override): step 4 now verifies limit placement - sql_examples: add nested-aggregation bad/good examples for all 11 engines showing the limit on the outer query only - Oracle: fix invalid GROUP BY...WHERE ROWNUM example and wrong ROWNUM-before-ORDER BY few-shot answers (wrap with outer query) --- .../templates/sql_examples/AWS_Redshift.yaml | 21 +++++++++++++++++ .../templates/sql_examples/ClickHouse.yaml | 21 +++++++++++++++++ backend/templates/sql_examples/DM.yaml | 21 +++++++++++++++++ backend/templates/sql_examples/Doris.yaml | 21 +++++++++++++++++ .../templates/sql_examples/Elasticsearch.yaml | 21 +++++++++++++++++ backend/templates/sql_examples/Hive.yaml | 21 +++++++++++++++++ backend/templates/sql_examples/Kingbase.yaml | 21 +++++++++++++++++ .../sql_examples/Microsoft_SQL_Server.yaml | 20 ++++++++++++++++ backend/templates/sql_examples/MySQL.yaml | 23 ++++++++++++++++++- backend/templates/sql_examples/Oracle.yaml | 22 ++++++++++++++---- .../templates/sql_examples/PostgreSQL.yaml | 23 ++++++++++++++++++- backend/templates/sql_examples/StarRocks.yaml | 21 +++++++++++++++++ backend/templates/template.yaml | 19 +++++++++++---- 13 files changed, 263 insertions(+), 12 deletions(-) diff --git a/backend/templates/sql_examples/AWS_Redshift.yaml b/backend/templates/sql_examples/AWS_Redshift.yaml index 768bdca6b..6bdb9db6e 100644 --- a/backend/templates/sql_examples/AWS_Redshift.yaml +++ b/backend/templates/sql_examples/AWS_Redshift.yaml @@ -71,6 +71,27 @@ template: FETCH FIRST 1000 ROWS ONLY + + + 统计订单表 TEST.ORDERS 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT "t"."customer_id" AS "customer_id", SUM("t"."amount") AS "total_amount" + FROM (SELECT "customer_id", "amount" FROM "TEST"."ORDERS" WHERE "create_time" >= '2024-01-01' LIMIT 100) "t" + GROUP BY "t"."customer_id" + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + "o"."customer_id" AS "customer_id", + SUM("o"."amount") AS "total_amount" + FROM "TEST"."ORDERS" "o" + WHERE "o"."create_time" >= '2024-01-01' + GROUP BY "o"."customer_id" + ORDER BY "total_amount" DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: AWS Redshift 1.0 diff --git a/backend/templates/sql_examples/ClickHouse.yaml b/backend/templates/sql_examples/ClickHouse.yaml index c2b56f2dd..67d9b1ae4 100644 --- a/backend/templates/sql_examples/ClickHouse.yaml +++ b/backend/templates/sql_examples/ClickHouse.yaml @@ -74,6 +74,27 @@ template: LIMIT 5 + + + 统计订单表 default.orders 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT "t"."customer_id" AS "customer_id", SUM("t"."amount") AS "total_amount" + FROM (SELECT "customer_id", "amount" FROM "default"."orders" WHERE "create_time" >= '2024-01-01' LIMIT 100) "t" + GROUP BY "t"."customer_id" + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + "o"."customer_id" AS "customer_id", + SUM("o"."amount") AS "total_amount" + FROM "default"."orders" "o" + WHERE "o"."create_time" >= '2024-01-01' + GROUP BY "o"."customer_id" + ORDER BY "total_amount" DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: ClickHouse 23.3 diff --git a/backend/templates/sql_examples/DM.yaml b/backend/templates/sql_examples/DM.yaml index df050f6e8..c87b9ad00 100644 --- a/backend/templates/sql_examples/DM.yaml +++ b/backend/templates/sql_examples/DM.yaml @@ -72,6 +72,27 @@ template: LIMIT 0, 1000 -- 达梦兼容写法 + + + 统计订单表 TEST.ORDERS 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT "t"."customer_id" AS "customer_id", SUM("t"."amount") AS "total_amount" + FROM (SELECT "customer_id", "amount" FROM "TEST"."ORDERS" WHERE "create_time" >= '2024-01-01' LIMIT 100) "t" + GROUP BY "t"."customer_id" + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + "o"."customer_id" AS "customer_id", + SUM("o"."amount") AS "total_amount" + FROM "TEST"."ORDERS" "o" + WHERE "o"."create_time" >= '2024-01-01' + GROUP BY "o"."customer_id" + ORDER BY "total_amount" DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: DM Database 8 diff --git a/backend/templates/sql_examples/Doris.yaml b/backend/templates/sql_examples/Doris.yaml index 9e16b7593..3580273a7 100644 --- a/backend/templates/sql_examples/Doris.yaml +++ b/backend/templates/sql_examples/Doris.yaml @@ -74,6 +74,27 @@ template: LIMIT 1000 + + + 统计订单表 test.orders 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT `t`.`customer_id` AS `customer_id`, SUM(`t`.`amount`) AS `total_amount` + FROM (SELECT `customer_id`, `amount` FROM `test`.`orders` WHERE `create_time` >= '2024-01-01' LIMIT 100) `t` + GROUP BY `t`.`customer_id` + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + `o`.`customer_id` AS `customer_id`, + SUM(`o`.`amount`) AS `total_amount` + FROM `test`.`orders` `o` + WHERE `o`.`create_time` >= '2024-01-01' + GROUP BY `o`.`customer_id` + ORDER BY `total_amount` DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: Apache Doris 2.0 diff --git a/backend/templates/sql_examples/Elasticsearch.yaml b/backend/templates/sql_examples/Elasticsearch.yaml index 14188c2f6..8c2b22509 100644 --- a/backend/templates/sql_examples/Elasticsearch.yaml +++ b/backend/templates/sql_examples/Elasticsearch.yaml @@ -88,6 +88,27 @@ template: LIMIT 5 + + + 统计 logs-* 索引中最近一天各个客户端IP的日志数量,返回数量最多的前100个IP + + SELECT "t"."host.ip" AS "client_ip", COUNT("t"."message") AS "log_count" + FROM (SELECT "host.ip", "message" FROM "logs-*" LIMIT 100) "t" + GROUP BY "t"."host.ip" + -- 严重错误:内层LIMIT导致聚合只基于被截断的100行数据计算,结果错误!Elasticsearch SQL也不支持FROM子查询 + + + SELECT + "l"."host.ip" AS "client_ip", + COUNT("l"."message") AS "log_count" + FROM "logs-*" "l" + WHERE CAST("l"."@timestamp" AS TIMESTAMP) > DATE_SUB(NOW(), INTERVAL 1 DAY) + GROUP BY "l"."host.ip" + ORDER BY "log_count" DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在整个查询的最外层 + + example_engine: Elasticsearch SQL 8.9 diff --git a/backend/templates/sql_examples/Hive.yaml b/backend/templates/sql_examples/Hive.yaml index f7998b930..88c530be0 100644 --- a/backend/templates/sql_examples/Hive.yaml +++ b/backend/templates/sql_examples/Hive.yaml @@ -71,6 +71,27 @@ template: WHERE `u`.`status` = 1 + + + 统计订单表 ods.orders 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT `t`.`customer_id` AS `customer_id`, SUM(`t`.`amount`) AS `total_amount` + FROM (SELECT `customer_id`, `amount` FROM `ods`.`orders` WHERE YEAR(`create_time`) = 2024 LIMIT 100) `t` + GROUP BY `t`.`customer_id` + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + `o`.`customer_id` AS `customer_id`, + SUM(`o`.`amount`) AS `total_amount` + FROM `ods`.`orders` `o` + WHERE YEAR(`o`.`create_time`) = 2024 + GROUP BY `o`.`customer_id` + ORDER BY `total_amount` DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: Apache Hive 2.X diff --git a/backend/templates/sql_examples/Kingbase.yaml b/backend/templates/sql_examples/Kingbase.yaml index e3fa4caa4..88f79f735 100644 --- a/backend/templates/sql_examples/Kingbase.yaml +++ b/backend/templates/sql_examples/Kingbase.yaml @@ -67,6 +67,27 @@ template: WHERE "u"."status" = 1 + + + 统计订单表 TEST.ORDERS 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT "t"."customer_id" AS "customer_id", SUM("t"."amount") AS "total_amount" + FROM (SELECT "customer_id", "amount" FROM "TEST"."ORDERS" WHERE "create_time" >= '2024-01-01' LIMIT 100) "t" + GROUP BY "t"."customer_id" + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + "o"."customer_id" AS "customer_id", + SUM("o"."amount") AS "total_amount" + FROM "TEST"."ORDERS" "o" + WHERE "o"."create_time" >= '2024-01-01' + GROUP BY "o"."customer_id" + ORDER BY "total_amount" DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: Kingbase V8 diff --git a/backend/templates/sql_examples/Microsoft_SQL_Server.yaml b/backend/templates/sql_examples/Microsoft_SQL_Server.yaml index 31bc77c5f..31a473e74 100644 --- a/backend/templates/sql_examples/Microsoft_SQL_Server.yaml +++ b/backend/templates/sql_examples/Microsoft_SQL_Server.yaml @@ -72,6 +72,26 @@ template: OFFSET 0 ROWS FETCH NEXT 1000 ROWS ONLY + + + 统计订单表 Sales.Orders 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT [t].[customer_id] AS [customer_id], SUM([t].[amount]) AS [total_amount] + FROM (SELECT TOP 100 [customer_id], [amount] FROM [Sales].[Orders] WHERE [create_time] >= '2024-01-01') [t] + GROUP BY [t].[customer_id] + -- 严重错误:TOP加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT TOP 100 + [o].[customer_id] AS [customer_id], + SUM([o].[amount]) AS [total_amount] + FROM [Sales].[Orders] [o] + WHERE [o].[create_time] >= '2024-01-01' + GROUP BY [o].[customer_id] + ORDER BY [total_amount] DESC + -- 正确:TOP只加在最外层查询上,聚合基于完整数据计算,只限制最终返回结果的行数 + + example_engine: Microsoft SQL Server 2022 diff --git a/backend/templates/sql_examples/MySQL.yaml b/backend/templates/sql_examples/MySQL.yaml index 36e27e818..e259a263b 100644 --- a/backend/templates/sql_examples/MySQL.yaml +++ b/backend/templates/sql_examples/MySQL.yaml @@ -63,7 +63,7 @@ template: SELECT `desc`, ROUND(active_ratio*100) FROM `public`.`users` -- 错误:百分比格式错误 - SELECT + SELECT `u`.`desc` AS `description`, CONCAT(ROUND(`u`.`active_ratio` * 100, 2), '%') AS `active_percent` FROM `public`.`users` `u` @@ -71,6 +71,27 @@ template: LIMIT 1000 + + + 统计订单表 test.orders 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT `t`.`customer_id` AS `customer_id`, SUM(`t`.`amount`) AS `total_amount` + FROM (SELECT `customer_id`, `amount` FROM `test`.`orders` WHERE `create_time` >= '2024-01-01' LIMIT 100) `t` + GROUP BY `t`.`customer_id` + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + `o`.`customer_id` AS `customer_id`, + SUM(`o`.`amount`) AS `total_amount` + FROM `test`.`orders` `o` + WHERE `o`.`create_time` >= '2024-01-01' + GROUP BY `o`.`customer_id` + ORDER BY `total_amount` DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: MySQL 8.0 diff --git a/backend/templates/sql_examples/Oracle.yaml b/backend/templates/sql_examples/Oracle.yaml index 248948ee7..6d058d246 100644 --- a/backend/templates/sql_examples/Oracle.yaml +++ b/backend/templates/sql_examples/Oracle.yaml @@ -4,7 +4,7 @@ template: 1. 分析用户问题,确定查询需求 2. 根据表结构生成基础SQL 3. 强制检查:逐字验证SQL中使用的表名和字段名是否在中定义,且字符必须完全匹配(包括繁简体、大小写、特殊字符),不得有任何转换。如发现任何不一致,必须重新生成SQL。 - 4. 强制检查:应用数据量限制规则(默认限制或用户指定数量) + 4. 强制检查:应用数据量限制规则(默认限制或用户指定数量),限制必须位于最外层查询,不得出现在子查询、派生表、CTE内部 5. 应用其他规则(引号、别名、格式化等) 6. 最终验证:GROUP BY查询的ROWNUM位置是否正确? 7. 强制检查:验证SQL语法是否符合规范 @@ -110,14 +110,26 @@ template: SELECT COUNT("订单ID") FROM "TEST"."ORDERS" "t1" -- 错误:函数未加别名 - SELECT + SELECT "order_id", "amount", "total_orders", "discount_percent" FROM ( + SELECT + "t1"."订单ID" AS "order_id", + "t1"."金额" AS "amount", + COUNT("t1"."订单ID") AS "total_orders", + TO_CHAR("t1"."折扣率" * 100, '990.99') || '%' AS "discount_percent" + FROM "TEST"."ORDERS" "t1" + GROUP BY "t1"."订单ID", "t1"."金额", "t1"."折扣率" + ) + WHERE ROWNUM <= 100 + + + SELECT "t1"."订单ID" AS "order_id", "t1"."金额" AS "amount", COUNT("t1"."订单ID") AS "total_orders", TO_CHAR("t1"."折扣率" * 100, '990.99') || '%' AS "discount_percent" FROM "TEST"."ORDERS" "t1" GROUP BY "t1"."订单ID", "t1"."金额", "t1"."折扣率" - WHERE ROWNUM <= 100 + FETCH FIRST 100 ROWS ONLY @@ -197,11 +209,11 @@ template: example_answer_1: | {"success":true,"sql":"SELECT \"country\" AS \"country_name\", \"continent\" AS \"continent_name\", \"year\" AS \"year\", \"gdp\" AS \"gdp\" FROM \"Sample_Database\".\"sample_country_gdp\" ORDER BY \"country\", \"year\"","tables":["sample_country_gdp"],"chart-type":"line"} example_answer_1_with_limit: | - {"success":true,"sql":"SELECT \"country\" AS \"country_name\", \"continent\" AS \"continent_name\", \"year\" AS \"year\", \"gdp\" AS \"gdp\" FROM \"Sample_Database\".\"sample_country_gdp\" WHERE ROWNUM <= 1000 ORDER BY \"country\", \"year\"","tables":["sample_country_gdp"],"chart-type":"line"} + {"success":true,"sql":"SELECT \"country_name\", \"continent_name\", \"year\", \"gdp\" FROM (SELECT \"country\" AS \"country_name\", \"continent\" AS \"continent_name\", \"year\" AS \"year\", \"gdp\" AS \"gdp\" FROM \"Sample_Database\".\"sample_country_gdp\" ORDER BY \"country\", \"year\") WHERE ROWNUM <= 1000","tables":["sample_country_gdp"],"chart-type":"line"} example_answer_2: | {"success":true,"sql":"SELECT \"country\" AS \"country_name\", \"gdp\" AS \"gdp\" FROM \"Sample_Database\".\"sample_country_gdp\" WHERE \"year\" = '2024' ORDER BY \"gdp\" DESC","tables":["sample_country_gdp"],"chart-type":"pie"} example_answer_2_with_limit: | - {"success":true,"sql":"SELECT \"country\" AS \"country_name\", \"gdp\" AS \"gdp\" FROM \"Sample_Database\".\"sample_country_gdp\" WHERE \"year\" = '2024' AND ROWNUM <= 1000 ORDER BY \"gdp\" DESC","tables":["sample_country_gdp"],"chart-type":"pie"} + {"success":true,"sql":"SELECT \"country_name\", \"gdp\" FROM (SELECT \"country\" AS \"country_name\", \"gdp\" AS \"gdp\" FROM \"Sample_Database\".\"sample_country_gdp\" WHERE \"year\" = '2024' ORDER BY \"gdp\" DESC) WHERE ROWNUM <= 1000","tables":["sample_country_gdp"],"chart-type":"pie"} example_answer_3: | {"success":true,"sql":"SELECT \"country\" AS \"country_name\", \"gdp\" AS \"gdp\" FROM \"Sample_Database\".\"sample_country_gdp\" WHERE \"year\" = '2025' AND \"country\" = '中国'","tables":["sample_country_gdp"],"chart-type":"table"} example_answer_3_with_limit: | diff --git a/backend/templates/sql_examples/PostgreSQL.yaml b/backend/templates/sql_examples/PostgreSQL.yaml index 268e8b7b5..0fe680e07 100644 --- a/backend/templates/sql_examples/PostgreSQL.yaml +++ b/backend/templates/sql_examples/PostgreSQL.yaml @@ -58,13 +58,34 @@ template: SELECT "user", ROUND(active_ratio) FROM "PUBLIC"."USERS" -- 错误:百分比格式错误 - SELECT + SELECT "u"."user" AS "username", ROUND("u"."active_ratio" * 100, 2) || '%' AS "active_percent" FROM "PUBLIC"."USERS" "u" WHERE "u"."status" = 1 + + + 统计订单表 TEST.ORDERS 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT "t"."customer_id" AS "customer_id", SUM("t"."amount") AS "total_amount" + FROM (SELECT "customer_id", "amount" FROM "TEST"."ORDERS" WHERE "create_time" >= '2024-01-01' LIMIT 100) "t" + GROUP BY "t"."customer_id" + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + "o"."customer_id" AS "customer_id", + SUM("o"."amount") AS "total_amount" + FROM "TEST"."ORDERS" "o" + WHERE "o"."create_time" >= '2024-01-01' + GROUP BY "o"."customer_id" + ORDER BY "total_amount" DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: PostgreSQL17.6 (Debian 17.6-1.pgdg12+1) diff --git a/backend/templates/sql_examples/StarRocks.yaml b/backend/templates/sql_examples/StarRocks.yaml index 212677fc4..73b9ed7b8 100644 --- a/backend/templates/sql_examples/StarRocks.yaml +++ b/backend/templates/sql_examples/StarRocks.yaml @@ -72,6 +72,27 @@ template: LIMIT 1000 + + + 统计订单表 test.orders 中2024年每个客户的消费总金额,返回金额最高的前100名客户 + + SELECT `t`.`customer_id` AS `customer_id`, SUM(`t`.`amount`) AS `total_amount` + FROM (SELECT `customer_id`, `amount` FROM `test`.`orders` WHERE `create_time` >= '2024-01-01' LIMIT 100) `t` + GROUP BY `t`.`customer_id` + -- 严重错误:LIMIT加在了内层子查询中,聚合只基于被截断的100行数据计算,结果错误! + + + SELECT + `o`.`customer_id` AS `customer_id`, + SUM(`o`.`amount`) AS `total_amount` + FROM `test`.`orders` `o` + WHERE `o`.`create_time` >= '2024-01-01' + GROUP BY `o`.`customer_id` + ORDER BY `total_amount` DESC + LIMIT 100 + -- 正确:聚合基于完整数据计算,LIMIT只限制最终返回结果的行数,且只出现在最外层查询 + + example_engine: StarRocks 3.0 diff --git a/backend/templates/template.yaml b/backend/templates/template.yaml index e9ab6c371..bc8f8274e 100644 --- a/backend/templates/template.yaml +++ b/backend/templates/template.yaml @@ -28,7 +28,7 @@ template: 1. 分析用户问题,确定查询需求 2. 根据表结构生成基础SQL 3. 强制检查:逐字验证SQL中使用的表名和字段名是否在中定义,且字符必须完全匹配(包括繁简体、大小写、特殊字符),不得有任何转换。如发现任何不一致,必须重新生成SQL。 - 4. 强制检查:应用数据量限制规则(默认限制或用户指定数量) + 4. 强制检查:应用数据量限制规则(默认限制或用户指定数量),限制必须位于最外层查询,不得出现在子查询、派生表、CTE内部 5. 应用其他规则(引号、别名、格式化等) 6. 强制检查:验证SQL语法是否符合规范 7. 确定图表类型(根据规则选择table/column/bar/line/pie) @@ -41,17 +41,22 @@ template: 数据量限制策略(必须严格遵守 - 零容忍) - 所有生成的SQL必须包含数据量限制,这是强制要求 + 每条生成的完整SQL语句,最外层查询必须包含数据量限制,这是强制要求 默认限制:1000条(除非用户明确指定其他数量,如"查询前10条") 当用户说"所有数据"或"全部数据"时,视为用户没有指定数量,使用默认的1000条限制 + 数据量限制只能应用在最外层查询上,限制的是最终返回结果的行数,而不是参与计算的数据量 + 禁止在子查询、派生表、CTE内部添加数据量限制,聚合、统计、排序等计算必须基于完整数据,否则会导致结果错误 忘记添加数据量限制是不可接受的错误 如果生成的SQL没有数据量限制,必须重新生成 - 在最终返回前必须验证限制是否存在 - 不要因为用户说"所有数据"而拒绝生成SQL,只需自动加上1000条限制即可 + 在最终返回前必须验证:数据量限制存在于最外层查询,且所有子查询内部均没有数据量限制 + 不要因为用户说"所有数据"而拒绝生成SQL,只需在最外层自动加上1000条限制即可 + + 用户明确要求的"每组前N"类需求(如"每个部门薪资最高的前3名"),属于分组内的行数条件:若数据库引擎支持窗口函数,应通过ROW_NUMBER()等窗口函数配合WHERE条件实现;若引擎不支持窗口函数,则使用该引擎支持的等效写法实现。这类分组内的行数条件不视为违反本规则 + no_query_limit: | @@ -59,11 +64,15 @@ template: 默认不限制数据量,返回全部数据(除非用户明确指定其他数量) 不要臆测场景可能需要的数据量限制,以用户明确指定的数量为准 - 用户明确说"前N条"、"限制N条"、"N条"等条件时,必须添加限制 + 用户明确说"前N条"、"限制N条"、"N条"等条件时,必须添加限制,且该限制只能应用在最外层查询上,限制的是最终返回结果的行数 + 禁止在子查询、派生表、CTE内部添加数据量限制,聚合、统计、排序等计算必须基于完整数据 不要拒绝查询所有数据的情况 + + 用户明确要求的"每组前N"类需求(如"每个部门薪资最高的前3名"),属于分组内的行数条件:若数据库引擎支持窗口函数,应通过ROW_NUMBER()等窗口函数配合WHERE条件实现;若引擎不支持窗口函数,则使用该引擎支持的等效写法实现。这类分组内的行数条件不视为在子查询内添加数据量限制 + multi_table_condition: |