Перестал работать ScriptedSandbox64.exe - Visual Studio 2015

Из ответов здесь можно сделать вывод, что NOT IN (subquery) неправильно обрабатывает нули и его следует избегать в пользу NOT EXISTS. Однако такой вывод может быть преждевременным. В следующем сценарии, зачисленном в Chris Date (Database Programming and Design, Vol 2 No 9, September 1989), NOT IN обрабатывает нули правильно и возвращает правильный результат, а не NOT EXISTS.

Рассмотрим таблицу sp для представления поставщиков (sno), которые, как известно, поставляют детали (pno) в количестве (qty). В таблице в настоящее время хранятся следующие значения:

      VALUES ('S1', 'P1', NULL), 
             ('S2', 'P1', 200),
             ('S3', 'P1', 1000)

Обратите внимание, что количество является нулевым, т. Е. Для записи факта, что поставщик, как известно, предоставляет детали, даже если в каком количестве неизвестно.

Задача состоит в том, чтобы найти поставщиков, которые известны номером запасной части «P1», но не в количествах 1000.

Следующие правила используют NOT IN для правильной идентификации поставщика S2, only:

WITH sp AS 
     ( SELECT * 
         FROM ( VALUES ( 'S1', 'P1', NULL ), 
                       ( 'S2', 'P1', 200 ),
                       ( 'S3', 'P1', 1000 ) )
              AS T ( sno, pno, qty )
     )
SELECT DISTINCT spx.sno
  FROM sp spx
 WHERE spx.pno = 'P1'
       AND 1000 NOT IN (
                        SELECT spy.qty
                          FROM sp spy
                         WHERE spy.sno = spx.sno
                               AND spy.pno = 'P1'
                       );

Однако в нижеприведенном запросе используется одна и та же общая структура, но с NOT EXISTS, но неверно включает в себя поставщик S1 в результате (т.е. для которого значение равно null):

WITH sp AS 
     ( SELECT * 
         FROM ( VALUES ( 'S1', 'P1', NULL ), 
                       ( 'S2', 'P1', 200 ),
                       ( 'S3', 'P1', 1000 ) )
              AS T ( sno, pno, qty )
     )
SELECT DISTINCT spx.sno
  FROM sp spx
 WHERE spx.pno = 'P1'
       AND NOT EXISTS (
                       SELECT *
                         FROM sp spy
                        WHERE spy.sno = spx.sno
                              AND spy.pno = 'P1'
                              AND spy.qty = 1000
                      );

Таким образом, NOT EXISTS не является серебряной пулей, она, возможно, появилась!

Конечно, источником проблемы является наличие нулей, поэтому «реальным» решением является устранение эти нули.

Это может быть достигнуто (среди других возможных конструкций) с использованием двух таблиц:

  • sp поставщиков, которые, как известно, поставляют детали
  • spq поставщиков, которые, как известно, поставляют детали в известных количествах

, отметив, что, вероятно, должно быть ограничение внешнего ключа, где spq ссылается sp.

Результат может тогда быть получена с использованием реляционного оператора «минус» (являющегося ключевым словом EXCEPT в стандартном SQL), например

WITH sp AS 
     ( SELECT * 
         FROM ( VALUES ( 'S1', 'P1' ), 
                       ( 'S2', 'P1' ),
                       ( 'S3', 'P1' ) )
              AS T ( sno, pno )
     ),
     spq AS 
     ( SELECT * 
         FROM ( VALUES ( 'S2', 'P1', 200 ),
                       ( 'S3', 'P1', 1000 ) )
              AS T ( sno, pno, qty )
     )
SELECT sno
  FROM spq
 WHERE pno = 'P1'
EXCEPT 
SELECT sno
  FROM spq
 WHERE pno = 'P1'
       AND qty = 1000;
30
задан Alexander Pacha 29 June 2016 в 17:27
поделиться