Как заменить начальные нулевые значения первым ненулевым значением в строке? - PullRequest
0 голосов
/ 11 августа 2010

Я постараюсь избежать описания фона здесь.Теперь у меня есть результат запроса (не таблица), который содержит такие строки:

ID      SP1     SP2     SP3     SP4     SP5    SP6     SP7     SP8
1       null    null    2500    1400    700    null    null    null

Могут быть начальные и / или конечные нулевые значения вокруг секции ненулевых значений (что представляет собой убывающий процессна самом деле).И то, что я хочу, выглядит следующим образом:

ID      SP1     SP2     SP3     SP4     SP5    SP6     SP7     SP8
1       2500    2500    2500    1400    700    0       0       0

Это означает, что заменить начальные нули на первое ненулевое значение, а конечные нули на 0.
Пожалуйста, сообщите.Я работаю на SQL Server 2000.

Ответы [ 2 ]

2 голосов
/ 11 августа 2010
SELECT
    ID,
    COALESCE(SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8,0) as SP1,
    COALESCE(SP2,SP3,SP4,SP5,SP6,SP7,SP8,0) as SP2,
    COALESCE(SP3,SP4,SP5,SP6,SP7,SP8,0) as SP3,
    COALESCE(SP4,SP5,SP6,SP7,SP8,0) as SP4,
    COALESCE(SP5,SP6,SP7,SP8,0) as SP5,
    COALESCE(SP6,SP7,SP8,0) as SP6,
    COALESCE(SP7,SP8,0) as SP7,
    COALESCE(SP8,0) as SP8
FROM
    (<your existing query>) t

COALESCE принимает ряд выражений и возвращает первое ненулевое значение.

1 голос
/ 11 августа 2010

Вы должны , вероятно, пересмотреть свою схему. Когда у вас есть что-то похожее на массив в одной строке, часто лучше разделить его на отдельные строки.

Но, предполагая, что вы застряли с текущей схемой, я бы просто сказал:

start transaction;
update TBL set SP8 =   0 where SP8 is null;
update TBL set SP7 = SP8 where SP7 is null;
update TBL set SP6 = SP7 where SP6 is null;
update TBL set SP5 = SP6 where SP5 is null;
update TBL set SP4 = SP5 where SP4 is null;
update TBL set SP3 = SP4 where SP3 is null;
update TBL set SP2 = SP3 where SP2 is null;
update TBL set SP1 = SP2 where SP1 is null;
commit;

(при необходимости подставляя правильный синтаксис транзакции SQL Server).

Если вы не хотите на самом деле изменять базовые данные, вы можете использовать представление, но оно, вероятно, будет отвратительным, и вы можете захотеть сделать трансформацию в любом приложении, которое у вас есть ' вместо этого используется для выполнения SQL.

Одна возможность, но я настоятельно призываю вас не делать этого, и может быть лучший способ для конкретного поставщика:

  • создает представление view8 над таблицей, которое оставляет все столбцы нетронутыми, за исключением SP8, который становится coalesce(sp8,0) (или любым другим эквивалентом SQL Server - SP8, если он не равен NULL, иначе 0).
  • создать представление view7 поверх представления view8, которое оставляет все столбцы без изменений, кроме SP7, который становится coalesce(sp7,sp8).
  • создать представление view6 поверх представления view7, которое оставляет все столбцы без изменений, кроме SP6, который становится coalesce(sp6,sp7).
  • бла, бла, бла.
  • создать представление view1 поверх вида view2, которое оставляет все столбцы без изменений, кроме SP1, который становится coalesce(sp1,sp2).
  • использовать вид view1.

Как я уже сказал, огромный клочок и, пожалуйста, ради любви к любым богам, в которых вы верите, не используйте его. Но иногда нужно диктовать наши действия, поэтому я выкладываю это на всякий случай.

Все заботы, никакой ответственности, протестируйте (и профилируйте) это сами.


И, опубликовав это и обнаружив, что Дэмиен имеет более компактную версию, я также хотел бы предложить следующее.

Иногда полезно пожертвовать пространством ради времени (ускорить процесс за счет увеличения занимаемого места на диске).

Вы можете создать еще 8 столбцов, от MORPHSP1 до MORPHSP8, для хранения измененных значений, которые я предложил в моем первом решении.

Это обычно нарушает 3NF, но на самом деле это нормально, если вы делаете две вещи: (1) понимаете последствия; и (2) уменьшить вероятность противоречивых данных.

Используя триггеры вставки / обновления, вы фактически можете гарантировать, что данные останутся непротиворечивыми.

При каждом изменении строки ваш триггер должен выполнять следующие действия.

set MORPHSP8 to coalesce (SP8,0)
set MORPHSP7 to coalesce (SP7,MORPHSP8)
set MORPHSP6 to coalesce (SP6,MORPHSP7)
set MORPHSP5 to coalesce (SP5,MORPHSP6)
set MORPHSP4 to coalesce (SP4,MORPHSP5)
set MORPHSP3 to coalesce (SP3,MORPHSP4)
set MORPHSP2 to coalesce (SP2,MORPHSP3)
set MORPHSP1 to coalesce (SP1,MORPHSP2)

Таким образом, вы несете расходы только при изменении данных, а не каждый раз, когда вы используете данные. В таблице, где число операций чтения превышает число записей (и это подавляющее большинство), это может привести к впечатляющему улучшению производительности.

...