← Все курсы · Курс SQL

Как просмотреть SQL, сгенерированный ИИ, прежде чем доверять числу

Майкл Носито · Обновлено в августе 2026 г. · Каждый запрос на этой странице был выполнен до его публикации.

Помощник ИИ напишет вам запрос за десять секунд, запрос будет выполнен, и полученное число будет выглядеть вполне разумным. На этой странице вы найдете пять проверок, которые помогут определить правильность этого числа. Они занимают около двух минут, им не нужны никакие инструменты, кроме уже имеющейся у вас базы данных, и они выявляют четыре ошибки, которые на самом деле допускает написанный ИИ SQL.

Порядок имеет значение. Чеки располагаются в первую очередь с наименьшими затратами, поэтому первый стоит одного подсчета строк, а последний стоит короткого разговора. Большинство неправильных запросов относятся к первым двум.

Краткая версия. Выполняемый запрос прошел только проверку грамматики. Число правильное, если строки, фильтры и знаменатель соответствуют заданному вами вопросу.

A query flows through two gates. The first gate, labeled "it ran", has a tick: the database checked the grammar. Between the first gate and the second gate, labeled "it is right", sits a gap bridged by five small ticks representing the five checks. The database takes the query to the first gate only. The five checks are what carry it to the second. query it ran ✓ ✓✓✓✓✓ five checks it is right
База данных принимает запрос только до первого шлюза.

Почему выполняемый запрос может быть неправильным

Перед списком: как вы думаете, что на самом деле проверяет база данных, когда принимает запрос?

Грамматика. Вот и весь список. Напишите имя таблицы неправильно, и вы получите ошибку. Суммируйте неправильный столбец, объединяйте строки так, чтобы удваивать их, или фильтруйте после группировки, когда вопрос требовал этого раньше, и вы получите чистый набор результатов с неправильным числом в нем. Каждая ошибка на этой странице — действительный SQL.

Помощники с искусственным интеллектом добавляют еще одну трудность: их запросы выполняются бегло. Псевдонимы аккуратные, форматирование чистое, а форма выглядит так, как будто написал внимательный человек. Беглость читается как правильность, а это не одно и то же. Относитесь к запросу ИИ так же, как к первому черновику от нового коллеги: с уважением и открытым счетчиком строк.

Таблица, на которой выполняются примеры

Все нижеприведенное работает на одном наборе данных небольшого магазина, поэтому каждое число можно проверить вручную. Тринадцать заказов в июле, пять клиентов и один refunds таблица, где возврат средств по двум заказам был разделен на две части. Одиннадцать из тринадцати заказов выполнены; один возвращен, другой находится на рассмотрении. Существует также staff_accounts таблица со списком внутренних учетных записей и содержит одну NULL-строку, поскольку в реальных таблицах поиска она обычно присутствует.

Валовая стоимость одиннадцати выполненных заказов составляет 1605 долларов. Всего возвратов — 275. Запомните эти две цифры.

Проверка 1: подсчитайте строки, прежде чем доверять сумме

До ответа: одиннадцать выполненных заказов, пять строк возврата. После LEFT JOIN от заказов к возвратам отображается ли запрос одиннадцать или более строк?

Вот запрос, который написал помощник для «чистого дохода от выполненных заказов»:

SELECT SUM(o.amount) - SUM(COALESCE(r.refund_amount, 0)) AS net_revenue
FROM orders o
LEFT JOIN refunds r ON r.order_id = o.order_id
WHERE o.status = 'completed';

Оно бежит. Он возвращает 1,830. Правильный ответ 1,330, что вы уже знаете, потому что 1605 минус 275 равно 1330.

Объединение — это проблема. Каждый из двух заказов был возвращен двумя частями, поэтому каждый из этих заказов соответствует двум строкам возврата. Соединение превращает одиннадцать строк в тринадцать, и SUM(o.amount) эти два заказа учитываются дважды: 2105 вместо 1605. Дополнительные 500 — это в точности стоимость двух двойных заказов. Это называется разветвлением: при соединении строки умножаются всякий раз, когда ключ на другой стороне появляется более одного раза.

Проверка стоит два пункта:

SELECT COUNT(*) FROM orders WHERE status = 'completed';        -- 11

SELECT COUNT(*)
FROM orders o LEFT JOIN refunds r ON r.order_id = o.order_id
WHERE o.status = 'completed';                                   -- 13

Одно это сравнение решает все. Если второе число выросло, соединение разветвилось, и каждая SUM или AVG в столбцах левой таблицы является подозрительной. Если оно выполнено, соединение безопасно, и вы можете двигаться дальше.

Проверка 2: найдите NULL в каждом фильтре

Следующим запросом была «та же выручка, без учета счетов персонала». Ассистент написал:

SELECT SUM(amount)
FROM orders
WHERE status = 'completed'
  AND customer_id NOT IN (SELECT customer_id FROM staff_accounts);

Это возвращает NULL, из нулевых строк. Не меньшее число. Ничего.

Скажите вслух, почему в staff_accounts может очистить весь результат, прежде чем читать дальше.

Вот механизм. NOT IN спрашивает для каждого заказа: «Отличается ли этот клиент от всех значений в списке?» Одно из значений в списке — NULL, и SQL не может определить, отличается ли что-либо от NULL. Сравнение возвращается «неизвестно», «неизвестное» неверно, и ни одна строка не сохраняется. Одна NULL-строка в таблице поиска автоматически очищает результат.

Исправление состоит в том, чтобы либо исключить NULL из списка, либо использовать NOT EXISTS, который не имеет такого поведения:

SELECT SUM(amount)
FROM orders o
WHERE o.status = 'completed'
  AND NOT EXISTS (SELECT 1 FROM staff_accounts s
                  WHERE s.customer_id = o.customer_id);   -- 1,395

Привычка рецензента: для каждого столбца, которого касается фильтр, спрашивать, что происходит с этим фильтром, когда столбец имеет значение NULL. Та же слепота тонет = NULL, который покрыт NULL в SQL.

Проверка 3: спросите, где находится фильтр, ГДЕ или ИМЕЕТ

Запрос был «клиенты, которые потратили более 400 на выполненные заказы». Какое условие должно удалять строки перед группировкой, а какое — проверять готовые итоги?

Версия ассистента:

SELECT c.name, SUM(o.amount) AS total
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id
GROUP BY c.name
HAVING SUM(o.amount) > 400;

Он возвращает трех клиентов: Эллис — 450, Диас — 420, Бун — 420. Правильный ответ: Эллис один. Диас пересекает отметку 400 только потому, что был засчитан отложенный ордер. Бун пересекает ее только потому, что был засчитан возвращенный заказ. Запрос никогда не фильтровался по статусу, поэтому группировка суммировала все.

В рассмотренной версии сначала фильтруются строки, а затем проверяются итоговые значения:

SELECT c.name, SUM(o.amount) AS total
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id
WHERE o.status = 'completed'
GROUP BY c.name
HAVING SUM(o.amount) > 400;                        -- Ellis, 450

Правило проверки: WHERE решает, какие строки разрешены в группы, HAVING решает, какие готовые группы допускаются в результат. Запрос ИИ, в котором упоминается статус, диапазон дат или сегмент только в HAVINGили нет вообще, заслуживает второго взгляда. Полная механика уже есть. GROUP BY и HAVING.

Проверка 4: назовите знаменатель

Запрос был «средняя стоимость выполненных заказов». Два запроса, оба беглые, оба работают чисто:

-- version A
SELECT AVG(amount) FROM orders WHERE status = 'completed';

-- version B
SELECT AVG(cust_avg) FROM (
  SELECT AVG(amount) AS cust_avg
  FROM orders
  WHERE status = 'completed'
  GROUP BY customer_id
);

Версия А возвращается 145.91. Версия Б возвращается 152.50. Ни то, ни другое не сломано. Они делятся по разным вещам. А делит сумму на одиннадцать порядков. B имеет в среднем пять средних значений на одного клиента, что дает покупателю с тремя небольшими заказами тот же вес, что и клиенту с двумя большими.

Кто из них прав, полностью зависит от вопроса. «Как выглядит типичный заказ» — это А. «Как выглядит типичный заказ клиента» — это Б. Помощник выбрал один, не спрашивая, потому что он должен был что-то выбрать. Вопрос рецензента всегда один и тот же: делится на что? Если вы не можете ответить на него из запроса, запрос не выполняется. Та же самая ловушка в форме электронной таблицы находится в проценты и сводные таблицы.

Проверка 5: заставить ИИ прочитать запрос обратно

Четыре проверки, описанные выше, являются механическими. Последний ловит всё остальное и сам использует помощника.

Попросите его повторить, пункт за пунктом, что делает запрос и почему каждое предложение отвечает заданному вами вопросу. Не резюме. Одна строка на каждое предложение в порядке запроса. Неправильный парафраз указывает на неправильное предложение с удивительной надежностью, потому что модель должна содержать утверждение о каждой части, а не описывать целое.

Это тот же блок чтения вслух из формат обучения и комментариев, используемый в качестве инструмента обзора. Рассмотренный запрос из проверки 1 выглядит следующим образом, когда он содержит комментарий:

/* WHY: Net July revenue from completed orders.
   Refunds arrive in parts, so refunds are totaled
   per order BEFORE the join. Joining the raw refunds
   table doubles multi-refund orders (13 rows vs 11). */

WITH refund_totals AS (
  SELECT order_id, SUM(refund_amount) AS refunded
  FROM refunds
  GROUP BY order_id
)
SELECT SUM(o.amount) - SUM(COALESCE(rt.refunded, 0)) AS net_revenue
FROM orders o
LEFT JOIN refund_totals rt ON rt.order_id = o.order_id
WHERE o.status = 'completed';                       -- 1,330

Представьте себе последний запрос, который ИИ написал для вас на работе. Проведите в уме проверку 1: каким будет число строк до объединения и после? Если вы не можете ответить по памяти, это запрос, который нужно будет проверить завтра.

Пограничные случаи, которые стоит знать

DISTINCT внутри агрегата — это сигнал, а не исправление. Когда ИИ пишет SUM(DISTINCT amount), это обычно встречало разветвление и подавляло симптом. Два разных заказа на 75 схлопываются в один, и сумма смещается в новую сторону. Вместо этого выполните предварительное агрегирование в CTE, как в проверке 5.

Иногда главное — это разветвление. Объединение заказов в позиции должен умножайте строки, потому что вопрос живет на уровне строки. Проверка не «выросли ли строки», а «выросли ли строки, когда вопрос их об этом не задавал».

NULL-поведение NOT IN это стандартный SQL, а не причуда одного движка. SQLite, PostgreSQL, MySQL и SQL Server — все это делают. Исправление путем очистки таблицы поиска работает до тех пор, пока следующий импорт не добавит обратно NULL. NOT EXISTS остается фиксированным.

Откуда это взялось

Предпосылка этой страницы о том, что AI SQL работает, но часто ошибается, является взвешенной, а не анекдотической. В тесте BIRD (12 751 вопрос в 95 реальных базах данных) самая надежная модель, протестированная в 2023 году, достигла точности выполнения 54,89 процента. Люди-инженеры достигли 92,96 процента по тем же вопросам. Точность выполнения означает, что результат запроса соответствует правильному результату, поэтому почти каждый сбой в этом интервале — это запрос, который выполнялся и возвращал неправильный ответ (Ли и др., 2023, Достижения в области нейронных систем обработки информации 36, наборы данных и контрольные показатели). С тех пор модели улучшились, и разрыв сократился, а не закрылся. Проверки на этой странице направлены на обнаруженные в тестах виды сбоев: неправильные соединения, неправильные фильтры, неправильная зернистость агрегации.

Как применить это в своей работе

  1. Поместите пять галочек там, где вы их увидите: строки, NULL, ГДЕ/имея, знаменатель, обратное чтение.
  2. В течение одной недели выполняйте проверки 1 и 2 для каждого запроса AI, прежде чем использовать его номер. Они стоят минуты.
  3. Если проверка не удалась, не устраняйте симптом. Попросите ассистента объяснить ошибочное предложение, а затем устраните причину.
  4. Сохраняйте заголовок WHY в фиксированном запросе, чтобы следующий читатель унаследовал рассуждения, а не только SQL.
  5. Не пытайтесь модифицировать каждый запрос ИИ, уже имеющийся в ваших файлах. Это жалкая работа. Просматривайте их по мере их появления, по одному.

Если у вас под рукой есть бумага, набросайте таблицы заказов и возвратов из проверки 1 и проведите по одной линии от каждого выполненного заказа до строк возврата. Два порядка, получающие две линии, — это целая история разветвления, и, нарисовав его один раз, вы увидите его в запросе до того, как его запустите.

Шпаргалка

ПроверитьБеги или спросиНеудача выглядит так
1. РядыCOUNT(*) до и после каждого соединенияКоличество строк выросло; суммы над левой таблицей завышены
2. НУЛЬЧто такое NULL в каждом отфильтрованном столбце?NOT IN ничего не возвращает; = NULL ничего не соответствует
3. Сиденье фильтраНаходится ли каждое условие в WHERE или HAVING, и должно ли оно быть?Статус или дата названы только после группировки или отсутствуют
4. Знаменательделится на что?Среднее из средних; процент неправильного целого
5. Повторное чтениеОдна строка в предложении, против вопросаПредложение, которое перефразируется неверно или пропускается.

Единственная привычка, которую нужно сохранить

Подсчитайте строки до и после каждого соединения. Это самая дешевая проверка на странице, она выявляет самые дорогостоящие ошибки и работает с человеческим SQL точно так же, как и с машинным.

Какой самый последний номер, который вам передал ИИ, который вы передали, не проверив, и кто из пяти уловил бы его, если бы он был неверным?

Каждый номер здесь был проведён до того, как был опубликован. Набор данных намеренно небольшой, поэтому вы можете перестроить его и проверить каждый результат вручную. 1830, пустой результат, список из трех клиентов и оба средних значения — это реальные результаты, а не иллюстрации.
Чеки выхватывают неправильный номер. Стандарт останавливает его написание.

Система комментариев SQL — это двухрежимный стандарт комментирования, 12-балльная критерий оценки и агент Клода или ЧатGPT, который проверяет каждый запрос, включая те, которые написал ИИ, на его соответствие.

Система комментариев SQL, 29 долларов США →

Хотите более широкий навык, а не контрольный список? SQL для аналитиков читает запросы построчно, используя повседневные слова, что является привычкой, на которой построены эти проверки. SQL для аналитиков, 19 $ →

Пишите запросы, а не просто просматривайте их.

тот Курс SQL охватывает SELECT, WHERE, JOIN и GROUP BY с отработанными примерами, практикой и пробным экзаменом, и все это в браузере. Если у вас еще нет базы данных для практики, начните с установка за пятнадцать минут.

Откройте набор SQL →

Или введите их самостоятельно по одному: открыть SQL-практикум, тринадцать запросов, каждый из которых добавляет что-то одно к последнему.