# 代码审查报告 **文件:** `data\demo-sqlfluff\src\07_structure.sql` **语言:** sql **耗时:** 226.0s **分析工具:** sqlfluff --- 总计: 30 | 错误: 29 | 警告: 1 | 建议: 0 静态分析 · 28 个问题 - 🔴 `sqlfluff:LT05` L1 L1: 行过长(97 > 80)。 建议: 将该行注释拆分为多行或精简文字,使长度不超过 80 个字符。 - 🔴 `sqlfluff:ST01` L3 L3: 不要在 CASE WHEN 语句中指定 'ELSE NULL'(冗余)。 建议: 删除 `ELSE NULL` 分支;当条件不满足时 CASE 会自然返回 NULL。 - 🔴 `sqlfluff:ST02` L13 L13: 不必要的 CASE 语句,建议改用 COALESCE 函数。 建议: 改为 `COALESCE(amount > 0, FALSE) AS positive`,效果与当前 CASE 一致。 - 🔴 `sqlfluff:ST03` L20 L20: 查询定义了 CTE "unused_cte" 但未使用。 建议: 删除未使用的 CTE `WITH unused_cte AS (...)`,直接从 `SELECT` 开始查询。 - 🔴 `sqlfluff:LT08` L23 L23: CTE 结束括号之后应有空行,但未找到。 建议: 在 CTE 的闭合括号 `)` 与后续 `SELECT` 之间插入一个空行。 - 🔴 `sqlfluff:ST04` L32 L32: ELSE 子句中的嵌套 CASE 语句可以展平。 建议: 合并为一个 CASE:`CASE WHEN a = 1 THEN b WHEN c = 1 THEN d END AS result`。 - 🔴 `sqlfluff:RF04` L35 L35: 不应将关键字用作标识符。 建议: 将别名 `result` 改为非关键字名称,例如 `result_value`。 - 🔴 `sqlfluff:AL08` L42 L42: 列别名 'id' 与第 41 行的列名重复。 建议: 为 `sub.id` 指定唯一别名,例如 `AS sub_id`,避免结果集列名冲突。 - 🔴 `sqlfluff:AM05` L45 L45: JOIN 子句应使用全限定名。 建议: 明确使用 `INNER JOIN`,并确保 ON 条件中的列均带表别名限定。 - 🔴 `sqlfluff:ST05` L46 L46: select_statement 子句中不应包含子查询,应改用 CTE。 建议: 将 JOIN 中的派生表提取为 CTE:`WITH sub AS (SELECT id FROM other_table) SELECT ... JOIN sub ON ...`。 - 🔴 `sqlfluff:LT02` L46 L46: 应在 'ON' 前换行,且 'ON' 前不应有缩进。 建议: 将 ON 子句放到新行,放在与 JOIN 同一层级:`(SELECT ...) AS sub ON a.id = sub.id;` - 🔴 `sqlfluff:ST06` L49 L49: SELECT 中应先写通配符和简单目标,再写计算与聚合。 建议: 将 `*` 移到最前,再写普通列,最后写 `SUM(amount)`,并给聚合结果命名。注意当前查询还缺少 GROUP BY 或窗口函数。 - 🔴 `sqlfluff:AL03` L50 L50: 列表达式没有别名,请使用显式 `AS` 子句。 建议: 为 `SUM(amount)` 添加别名:`SUM(amount) AS total_amount`。 - 🔴 `sqlfluff:AM05` L62 L62: JOIN 子句应使用全限定名。 建议: 将 `USING (id)` 改写为带表别名限定的 ON 条件,并可加上 `INNER`。 - 🔴 `sqlfluff:LT02` L63 L63: 应在 'USING' 前换行,且不应缩进。 建议: 将 `USING (id)` 移到新行(若改写为 ON 也保持换行)。 - 🔴 `sqlfluff:ST07` L63 L63: 发现 USING 语句,应只使用 ON 语句。 建议: 将 `USING (id)` 改写为 `ON a.id = b.id`。 - 🔴 `sqlfluff:LT10` L66 L66: 'SELECT' 修饰符(如 'DISTINCT')必须与 'SELECT' 在同一行。 建议: 将 `DISTINCT` 移到 `SELECT` 同一行:`SELECT DISTINCT id`。 - 🔴 `sqlfluff:LT02` L67 L67: 该行不应缩进。 建议: 将 `DISTINCT` 移到 `SELECT` 同一行,消除缩进。 - 🔴 `sqlfluff:LT01` L67 L67: 'DISTINCT' 关键字与左括号 '(' 之间应有单个空格。 建议: 不要使用函数式写法;最好是去掉括号写成 `DISTINCT id`。 - 🔴 `sqlfluff:ST08` L67 L67: 'DISTINCT' 不能与括号一起使用。 建议: 去掉括号:`SELECT DISTINCT id`。 - 🔴 `sqlfluff:AM05` L77 L77: JOIN 子句应使用全限定名。 建议: 明确写出 `INNER JOIN`,并保持 ON 条件使用表别名限定。 - 🔴 `sqlfluff:LT02` L78 L78: 应在 'ON' 前换行,且不应缩进。 建议: 将 `ON` 子句放到新行:`other_table AS b ON b.id = a.id;` - 🔴 `sqlfluff:ST09` L78 L78: JOIN 条件应把先出现的表放在前面。 建议: 将 `ON b.id = a.id` 调整为 `ON a.id = b.id`。 - 🔴 `sqlfluff:ST10` L86 L86: 冗余常量表达式。 建议: 删除 `WHERE` 子句,或改为 `WHERE TRUE`;如果动态生成条件,请不要保留恒真条件。 - 🔴 `sqlfluff:ST11` L94 L94: JOIN 表 'other_table AS b' 未在查询其他位置引用。 建议: 若确实不需要该表,删除整个 LEFT JOIN;若只想判断存在性,请改用 EXISTS 子查询。 - 🔴 `sqlfluff:LT02` L94 L94: 应在 'ON' 前换行,且不应缩进。 建议: 将 `ON` 子句放到新行:`other_table AS b ON a.id = b.id;` - 🔴 `sqlfluff:ST12` L100 L100: 检测到连续分号(计数 2)。 建议: 删除多余的分号,只保留一个 `;`。 - 🔴 `sqlfluff:LT12` L101 L101: 文件必须以单个尾随换行符结束。 建议: 确保文件末尾恰好有一个换行符,不要多出空行或缺少换行。 AI 审查 · 2 条建议 - 🔴 [AI] [bug] `aggregate-without-group-by` L49 **聚合函数与未分组列/通配符混用** 第49行的 SELECT 将 `SUM(amount)` 与 `id`、`*` 放在同一个 SELECT 列表中,但没有 GROUP BY,也没有把 `SUM` 改为窗口函数。在大多数 SQL 引擎中这是非法查询;即使某些引擎允许,也会随机返回非聚合列的任意行,结果不可预测。 建议: 如果希望保留每一行并附带总额,使用窗口函数 `SUM(amount) OVER () AS total_amount`;如果希望做聚合,则需要列出所有非聚合列并加 `GROUP BY`,或显式只保留聚合结果。 - 🟡 [AI] [bug] `unused-left-join-cardinality` L94 **未使用的 LEFT JOIN 可能使结果行数倍增** 第93-94行的 LEFT JOIN 虽然未在 SELECT 或 WHERE 中引用 `other_table AS b`,但 SQL 仍会执行关联;若 `other_table.id` 有重复值,每条匹配都会复制左表行,导致结果集意外膨胀。静态规则只报告了表未被引用,但没有强调行数变化风险。 建议: 完全移除该 LEFT JOIN;若需要检查是否存在匹配,使用 `WHERE EXISTS (SELECT 1 FROM other_table b WHERE b.id = a.id)`。