我会尽量避免在这里描述背景。我现在有一个查询结果(不是表),其中包含如下行:
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。
答案 0 :(得分:2)
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 :(得分:1)
您可能会重新执行您的架构。每当你在一行中看起来像一个数组时,通常最好将它拆分成单独的行。
但是,假设您坚持使用当前架构,我只想简单地说:
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
之外,所有列都保持不变,如果不是view7
否则为0)。view8
上创建一个视图SP7
,除了coalesce(sp7,sp8)
成为view6
之外,所有列都保持不变。view7
上创建一个视图SP6
,除了coalesce(sp6,sp7)
成为view1
之外,所有列都保持不变。view2
上创建一个视图SP1
,除了coalesce(sp1,sp2)
成为view1
之外,所有列都保持不变。MORPHSP1
。正如我所说的那样,为了对你所信仰的众神的爱,请不要使用它。但有时需要决定我们的行为,所以我把它放在那里以防万一。
所有关心,没有责任,自己测试(和描述)。
而且,发布并发现Damien有一个更紧凑的版本,我也想提供以下内容。
有时候牺牲空间是有用的(以更多的磁盘空间为代价来加快速度)。
您可以创建另外8列MORPHSP8
到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)
,以存储我在第一个解决方案中建议的变形值。
这通常会违反3NF,但如果你做两件事,那实际上是可以的:(1)了解其后果; (2)减少数据不一致的可能性。
通过使用插入/更新触发器,您实际上可以保证数据保持一致。
只要行发生变化,您的触发器就会执行以下操作。
{{1}}
这样,您只需在数据发生变化时产生费用,而不是每次您使用数据。在读取数量超过写入的表格上(这是绝大多数),这可以带来令人印象深刻的性能提升。