2014-12-08 2 views
0

Я пытаюсь разобраться с большим набором хранимых процедур базы данных, которые я поддерживаю, и я пришел к чему-то запутанному. Я не могу сказать, содержит ли он избыточный/бесполезный код, или если мне не хватает какого-то нюанса, поскольку я все еще только промежуточный на языке SQL. Вот часть кода вопроса:Оператор SQL CASE, один результат кажется недостижимым

UPDATE #NewValues 
SET ValidNumber = CASE WHEN SP.ModelNumber IS NULL THEN 0 
          ELSE 1 
         END 
FROM #NewValues NV 
LEFT OUTER JOIN Stage.Products SP 
    ON NV.SKU = SP.SKU 
    AND (NV.ModelNumber = SP.ModelNumber OR NV.UPC = SP.ModelNumber) 
WHERE NV.SKU IN (
    SELECT NV.SKU 
    FROM #NewValues NV 
    INNER JOIN Stage.Products SP 
     ON NV.SKU = SP.SKU 
     AND (NV.ModelNumber = SP.ModelNumber OR NV.UPC = SP.ModelNumber) 
    WHERE NV.ValidNumber = 1 
) 

От работы через это, мне кажется, как будто нет ни одного случая, в котором SP.ModelNumber будет NULL, так как вложенная SELECT заявление никогда не вернется SKUs с SP.ModelNumber NULL результатов , Так что единственное, что может когда-либо сделать, это SET ValidNumber = 1. Это верно? Опять же, я не уверен, что здесь происходит что-то еще, что я не могу вставить в логику, но похоже, что вложенный оператор SELECT будет всем, что вам нужно будет использовать для достижения тех же результатов. Из-за того, как этот код позиционируется в гораздо большем запросе, у меня очень сложное время, пытаясь настроить ситуацию, которая будет соответствовать нормальному использованию, чтобы проверить это, тем более, что я не уверен, что значения ValidNumber будут до этот раздел кода работает.

+1

Это то, что мы назвали «Идиотским доказательством».Вы можете быть удивлены, как люди будут вводить данные самым неожиданным образом. В качестве стороннего разработчика мы должны учитывать ВСЕ виды возможных глупых способов (без обид) люди будут вводить данные. Просто побочная шутка: Вы когда-нибудь видели предупреждающую надпись на феном: «Не используйте это в душе? –

+0

только потому, что хотя бы один из sku имеет номер модели vaild, это не означает, что все эти sku имеют действительные modelNumbers – Beth

ответ

2

Это зависит от характера данных. Если один Sku может иметь несколько записей в таблице newvalues, тогда может понадобиться outer join, и было бы возможно установить validnumber = 0.


Вот некоторые примеры данных, чтобы попытаться показать (скрипку ниже):

create table newvalues (validnumber int, sku int, modelnumber int, upc int); 
create table products (sku int, modelnumber int); 

insert into newvalues values (1, 1, 1, 1), (0, 1, 1, 1), (null, 1, 2, 2); 
insert into products values (1, 1); 

Как вы можете видеть, есть несколько результатов в таблице newvalues ​​с sku = 1.


И тогда update заявление:

UPDATE NewValues 
SET validnumber = CASE WHEN SP.ModelNumber IS NULL THEN 0 
          ELSE 1 
         END 
FROM NewValues NV 
LEFT OUTER JOIN Products SP 
    ON NV.SKU = SP.SKU 
    AND (NV.ModelNumber = SP.ModelNumber OR NV.UPC = SP.ModelNumber) 
WHERE NV.SKU IN (
    SELECT NV.SKU 
    FROM NewValues NV 
    INNER JOIN Products SP 
     ON NV.SKU = SP.SKU 
     AND (NV.ModelNumber = SP.ModelNumber OR NV.UPC = SP.ModelNumber) 
    WHERE NV.ValidNumber = 1 
); 

Это обновляет все строки, некоторые до 0, а некоторые до 1, потому что по крайней мере один из тех, кто существовал в подзапрос с inner join. Это не будет отрицать outer join, поскольку существует несколько строк для одного и того же sku, поэтому все они обновляются (даже те, где sp.modelnumber is null)

+0

Спасибо за объяснение. Я понял, что мне не хватает аспекта того, как данные, уже существующие в таблицах, могут быть структурированы. Одна нота: мне пришлось использовать 'insert into newvalues ​​select (1, 1, 1, 1) union all select (0, 1, 1, 1) union all select (null, 1, 2, 2)', чтобы получить несколько строк вставлено. Наверное, это изменение для более поздних версий SQL-сервера? Я использую 2005. –

0

Оригинальный кодер просто безопасен. Существует вероятность того, что в #NewValues, который не существует в Stage.Product, может существовать элемент, и если это так, LEFT JOIN приведет к тому, что все поля в SP будут NULL, где нет совпадения.

+0

Да, но вы удаляете значения «NULL» в предложении 'where'? – Hatsjoem

+0

Это обновление, так что, если оно было действительно и больше не существует, потому что оно было удалено? – Jeremy

+0

За исключением того, что они также устраняются предложением where, потому что запрос предложения where использует внутреннее соединение по одинаковым критериям, что гарантирует, что любой SKU, в котором левое соединение создаст нулевой номер SP.ModelNumber, будет устранен тем, где in внутреннее соединение. –

0

Возможно, я ошибаюсь, но для чего вы используете первый WHERE?

WHERE NV.SKU IN (
    SELECT NV.SKU 
    FROM #NewValues NV 
    INNER JOIN Stage.Products SP 
     ON NV.SKU = SP.SKU 
     AND (NV.ModelNumber = SP.ModelNumber OR NV.UPC = SP.ModelNumber) 
    WHERE NV.ValidNumber = 1 
) 

Вы делаете то же самое JOIN здесь, как и в верхней.

Я хотел бы пойти на:

UPDATE #NewValues 
SET ValidNumber = CASE WHEN SP.ModelNumber IS NULL THEN 0 
         ELSE 1 
        END 
FROM #NewValues NV 
INNER JOIN Stage.Products SP 
    ON NV.SKU = SP.SKU 
    AND (NV.ModelNumber = SP.ModelNumber OR NV.UPC = SP.ModelNumber) 
WHERE NV.ValidNumber = 1 
Смежные вопросы