ОБНОВЛЕНИЕ, с помощью оператора CASE, игнорируя значения NULL

#sql #sql-server

Вопрос:

Мой приведенный ниже код плохо работает при попытке обновить таблицу, содержащую чуть более 100 000 строк.

У меня около 2500 значений, в которых первое значение в последовательности равно нулю, в результате эта строка и следующие последовательности не обновляются.

Кроме того, около 5000 строк также не обновляются, поскольку они не существуют во второй из двух таблиц (таблица 1 = dbo.abc / таблица 2 = dbo.abc_d)

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

 UPDATE dbo.abc abc
SET    vcn1 = ( CASE
                  WHEN abc.chan_id1 IS NOT NULL THEN abc.chan_id1
                  WHEN abc.chan_id2 IS NOT NULL THEN abc.chan_id2
                  WHEN abc.chan_id3 IS NOT NULL THEN abc.chan_id3
                  --omitting this chuck for readability
                  WHEN abc_d.chan_id34 IS NOT NULL THEN abc_d.chan_id34
                  WHEN abc_d.chan_id35 IS NOT NULL THEN abc_d.chan_id35
                  WHEN abc_d.chan_id36 IS NOT NULL THEN abc_d.chan_id36
                END ),
       vcn2 = ( CASE
                  WHEN abc.chan_id1 IS NOT NULL AND abc.chan_id1 != abc.vcn1 THEN abc.chan_id1
                  WHEN abc.chan_id2 IS NOT NULL AND abc.chan_id2 != abc.vcn1 THEN abc.chan_id2
                  WHEN abc.chan_id3 IS NOT NULL AND abc.chan_id3 != abc.vcn1 THEN abc.chan_id3
                  --omitting this chuck for readability
                  WHEN abc_d.chan_id34 IS NOT NULL AND abc_d.chan_id34 != abc.vcn1 THEN abc_d.chan_id34
                  WHEN abc_d.chan_id35 IS NOT NULL AND abc_d.chan_id35 != abc.vcn1 THEN abc_d.chan_id35
                  WHEN abc_d.chan_id36 IS NOT NULL AND abc_d.chan_id36 != abc.vcn1 THEN abc_d.chan_id36
                END )
FROM   dbo.abc_d abc_d
WHERE  abc.abc_id = abc_d.abc_id; 
 

Комментарии:

1. Я думаю, ваша проблема не ясна. В любом случае, не было бы проще, если бы вы заменили эти case when …. end на Coalesce(abc.chan_id1, abc.chan_id2, abc.chan_id3, … abc_d.chan_id34 …) Кстати, для второй проблемы вы могли бы использовать левое соединение.

2.Синтаксис, который у вас есть, недопустим; вы не можете использовать псевдоним таблицы в UPDATE предложении. Приведенное выше также приведет к возникновению ошибки Incorrect syntax near 'abc'. , это CASE выражение; оно возвращает скалярное значение.

3. Ваша реальная проблема заключается в отсутствии нормализации: у вас не должно быть 36 одинаковых столбцов

4. @Charlieface, унаследованная мной база данных — это беспорядок … много таблиц с несколькими одинаковыми столбцами, как у меня в этом выпуске. Можете ли вы указать мне какие-либо ресурсы, которые могли бы указать мне путь к исправлению этой базы данных?

5. Может быть, начать здесь sqlshack.com/what-is-database-normalization-in-sql-server их должно быть много в Интернете, если вы пользуетесь Google

Ответ №1:

Вы можете использовать левое соединение для решения вашей второй проблемы. Ваша первая проблема не является проблемой:

 UPDATE dbo.abc
SET    vcn1 = coalesce( abc.chan_id1, 
                        abc.chan_id2, 
                        abc_d.chan_id34,
                        abc_d.chan_id35
                ),
       vcn2 = ( CASE
                  WHEN abc.chan_id1 IS NOT NULL AND abc.chan_id1 != abc.vcn1 THEN abc.chan_id1
                  WHEN abc.chan_id2 IS NOT NULL AND abc.chan_id2 != abc.vcn1 THEN abc.chan_id2
                  WHEN abc_d.chan_id34 IS NOT NULL AND abc_d.chan_id34 != abc.vcn1 THEN abc_d.chan_id34
                  WHEN abc_d.chan_id35 IS NOT NULL AND abc_d.chan_id35 != abc.vcn1 THEN abc_d.chan_id35
                END )
FROM  dbo.abc abc 
left join dbo.abc_d abc_d
on  abc.abc_id = abc_d.abc_id; 
 

Вот демонстрация DBFiddle

Комментарии:

1. Привет, Четин. Я обновлю свои знания SQL и попробую опцию coalesce. Спасибо. Могу ли я также использовать coalesce во втором операторе case (VCN2)?

2. @RichardConaway, ну, во втором случае есть более сложное сравнение, которое на самом деле, я думаю, неверно, но я просто следовал вашему выражению. Coalesce(), похоже, не подходит для этого напрямую, но я действительно не понял, что вы пытаетесь там установить. Проверьте пример DbFiddle. Когда VCN1 равно NULL, сопоставление в любом случае завершается неудачно, а VCN2 равно NULL в конце. Вероятно, вместо этого вы имели в виду что-то вроде: vcn2 = ( СЛУЧАЙ, КОГДА abc.chan_id1 НЕ РАВЕН НУЛЮ И (abc.vcn1 равно нулю или abc.chan_id1 != abc.vcn1) ТОГДА abc.chan_id1 КОГДА …

3. FWIW abc.chan_id1 IS NOT NULL AND abc.chan_id1 != abc.vcn1 NULL проверка здесь не нужна, поскольку для проверки равенства [in], чтобы привести к true нему, оно должно быть ненулевым !