Разница между операторами SQL
Я столкнулся с двумя версиями программы SQLRPGLE и увидел изменение в коде, как показано ниже:
До:
Exec Sql SELECT 'N'
INTO :APRFLG
FROM LG751F T1
INNER JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y';
После:
Exec Sql SELECT case
when T1.ISAPRV <> 'Y' then 'N'
else T1.ISAPRV
end as APRFLG
INTO :APRFLG
FROM LG751F T1
join LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y'
group by T1.ISAPRV;
Не могли бы вы сказать мне, если вы видите разницу в том, как коды будут работать по-другому? Второй SQL имеет группу, которая должна быть исправлена, чтобы избежать ошибки -811 SQLCod. Кроме этого, вы, ребята, замечаете разницу?
3 ответа
Они оба являются примерами плохого кодирования IMO.
Требование "удалить дубликаты" часто является признаком плохого дизайна выписки и / или плохого дизайна БД.
Вы, кажется, делаете проверку существования, и в этом случае вы должны использовать EXISTS
сказуемое.
select 'N' into :APRFLG
from sysibm.sysdummy1
where exists (select 1
FROM LG751F T1
INNER JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN
AND T1.ISITNO = T2.IDMDNO
WHERE
T2.IDVIN = :M_VIN
AND T1.ISAPRV <> 'Y');
Что касается первоначальных двух утверждений, кроме группировки по, единственное реальное отличие состоит в перемещении столбцов из JOIN
пункт к WHERE
пункт. Тем не менее, механизм запросов в Db2 для i будет перезаписывать оба оператора одинаково и придумать тот же план; так как используется внутреннее соединение.
РЕДАКТИРОВАТЬ: как отмечает Марк, там JOIN
а также WHERE
одинаковы в обоих заявлениях ФП. Но я оставлю заявление выше в качестве FYI.
Я не нахожу убедительного различия, кроме добавления группы с помощью, которое будет подавлять любые дублирующиеся строки, которые могли быть выведены.
Похоже, что разработчик хотел, чтобы запрос мог изменять его выходные данные, чтобы быть иногда Y и иногда N, но забыл удалить предложение WHERE, которое обязательно заставляет регистр всегда быть истинным, и, следовательно, он всегда выводит N. Это Такая схема обычно проявляется, когда в исходном отчете указывается какая-то спецификация, например "не включать менеджеров в отчет Сакарья о сотрудниках", а затем меняется на "на самом деле мы хотим знать, является ли работник менеджером или нет". То, что было "где сотрудник не равный менеджер", становится "случаем, когда сотрудник является менеджером, тогда... еще…", но предложение where нужно удалить, чтобы оно имело какой-либо эффект
Внутреннее ключевое слово исчезло из оператора соединения, но в целом это также должно быть неоперативным
Другой вариант просто использовать fetch first row only
как это:
Exec Sql
SELECT 'N'
INTO :APRFLG
FROM LG751F T1
JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y'
fetch first row only;
Это делает более очевидным, что вы хотите только одну строку, а не пытаться использовать группировку, которая требует от фанка ничего не делать CASE
заявление. Но мне нравится EXISTS
метод, предложенный Чарльзом, так как это реальная цель, и наличие там делает его кристально ясным.
Если ваш лидер настаивает на GROUP BY
Вы также можете GROUP BY 'N'
и до сих пор опустить CASE
заявление.