Разница между операторами 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 заявление.

Другие вопросы по тегам