|
如果第一列(左侧列)的值为0,并且需要在右侧列中添加NULL,则需要将数据(列)移至左侧。一旦在任何列中找到非零值,则后面的列中的0值应保持原样。
, T( o* G8 g6 R* Y/ _输入数据:-
' n) k8 V& G' Hcust_id month1 month2 month3 month4 month5! l+ ]2 ?! A9 q% f( H, D
c1 100 200 300 400 500
0 J; h( E$ E$ N7 T$ @c2 0 0 50 250 350
) }8 f9 K6 H% D: H, q* X3 t; ac3 0 0 100 0 0
- P! a- n- w4 X0 B8 j2 @# Nc4 100 0 100 0 500- g& _/ h9 _1 `, y! v, S
c5 0 0 0 0 0
! R2 q, p) W! A x0 N- I预期的输出结果:-3 G" s+ R' C* u- Q
cust_id month1 month2 month3 month4 month5
$ E+ i2 ~( h% X; U5 h' Ic1 100 200 300 400 500
: W' d8 d5 Z: Tc2 50 250 350 NULL NULL; r/ x) f7 I6 P2 {% l
c3 100 0 0 NULL NULL
" C+ O& T$ y$ Z! w) Tc4 100 0 100 0 500& M+ i6 N+ C5 a0 x5 A
c5 NULL NULL NULL NULL NULL6 m: b$ d$ v5 s
一种静态的解决方法可能是:
( d! B+ W$ R" EIF month1=0 and month2=0 and month3=0 and month4=0 and month5=0
2 L; B: |3 v7 ZTHEN INSERT INTO TABLE output_table AS SELECT cust_id,'NULL','NULL','NULL','NULL','NULL' FROM input_table- {* Y' o k( C# l
IF month1=0 and month2=0 and month3=0 and month4=0 and month5 != 0
7 E7 A) J, N! L/ xTHEN INSERT INTO TABLE output_table AS SELECT cust_id,month5,'NULL','NULL','NULL','NULL' FROM input_table1 l- L8 Q+ M' P& ~' m- R
IF month1=0 and month2=0 and month3=0 and month4 != 0 and month5 != 0 1 Y( M6 _. Y4 v. j) y5 k
THEN INSERT INTO TABLE output_table AS SELECT cust_id,month4,month5,'NULL','NULL','NULL' FROM input_table2 e1 N- x" B( N K
IF month1=0 and month2=0 and month3 !=0 and month4 != 0 and month5 != 0
" ]& t7 t4 C6 b" x7 Z7 W1 hTHEN INSERT INTO TABLE output_table AS SELECT cust_id,month3,month4,month5,'NULL','NULL' FROM input_table
0 l8 i) z1 X4 P* L' |IF month1 != 0 and month2 != 0 and month3 !=0 and month4 != 0 and month5 != 0
9 _: n- ^7 z7 OTHEN INSERT INTO TABLE output_table AS SELECT cust_id,month1,month2,month3,month4,month5,'NULL' FROM input_table$ P W8 {# L/ u: i% k; a
我可以在下面找到线索,该线索解释了如果所有列都为空,则将列向左移动。但是它将替换所有NULL(即使NULL出现在任何非零/非null值之后)。- \' l) [& [; h( B/ [
我计划构建一个动态解决方案,以便在添加按月数据时可以处理新列。, v% i6 V3 w( S1 R5 `
[如果left包含null,right包含value,则将单元格在sql中向左移动
8 v: k5 h6 F4 q7 n3 b7 L数据库是:MS SQL Server 2012。5 S* x; k9 e; R/ b6 n1 t
快速SQL准备数据:- d& x$ Q8 s: E& f
CREATE TABLE input_table($ H; k* [) y6 C. L1 e, D6 g/ _' O
cust_id char(5),
9 d3 u( c4 Z* j' M month1 int,
" [% L2 w* { M$ P2 `6 r month2 int,
1 y* L; |2 Q+ M7 t( W month3 int,3 y( t8 O5 U" t) }- [# M
month4 int,
5 Q% D$ M+ d9 ]- p5 D2 {6 U month5 int
1 `- L* E3 x0 g);
( o, m0 L6 n5 D" w$ N/ s' c! K- l- G+ r
INSERT INTO input_table VALUES 2 E9 j0 G9 C! O+ |7 h1 K
('c1',100,200,300,400,500),- s+ [: @) J+ r& g, [
('c2',0,0,50,250,350),
; P# Y3 Y6 `2 p9 B4 P c% j/ j' _('c3',0,0,100,0,0),
4 f, e- d2 J' I& w4 o I6 L('c4',100,0,100,0,500),% z f0 \* b! Y6 S, I0 ?
('c5',0,0,0,0,0);& d+ {7 t8 {, N2 `
1 ?1 R4 E$ M! W5 v# ~- x解决方案:1 ?4 i) s! F6 l5 ^! h6 _
# o; E4 M8 l- q
* ]. X3 K% N( R, |4 Y- m2 F, }+ T2 h) c
这应该可以满足您的需求(演示)
; a$ ?4 ~ {6 k$ N- K$ oSELECT i.cust_id,
# s; H' I, J) z* h6 Y; O# ] oa.*
9 ^: p+ b5 y# d$ m+ k& k, e) wFROM input_table i( Y" J# t, a! o, P2 M
OUTER APPLY (SELECT pvt.*
; \& t" z1 i. f FROM (SELECT month,
{6 Q! s1 r7 f9 p# d% p col = CONCAT('month', ROW_NUMBER() OVER (ORDER BY idx))# P+ M# ]; a/ d& S, c5 q, ?# H
FROM (SELECT month,+ ?) ^9 f0 h6 \
idx,
5 e+ ^4 s; g, a) j to_preserve = MAX(IIF(month=0,0,1)) OVER (ORDER BY idx)# t$ m" S; R% ~2 | f2 O
FROM (VALUES (1, month1),1 U8 n& F& J* U( G/ G* A3 G
(2, month2),
4 T2 V% ^! G8 F) @ (3, month3),& U0 B+ q2 ]1 U* l% r, J
(4, month4),1 g# M3 b+ a9 F' k: n- P) ?
(5, month5) ) V(idx, month)) unpvt
3 |! l; i1 _# g# i/ E z! r WHERE to_preserve = 1) t
2 w* ~6 R( C3 A# o PIVOT (MAX(month) FOR col IN (month1, month2, month3, month4, month5)) pvt/ a% @, z' a ]" w4 t( E
) oa+ t3 x# c/ [6 J: i
它一次将列值取消透视。
; e* [! \* l4 s4 L例如,C3最终将毫无保留地
* n* a# J; M4 a, F4 R+---------+-------+-----+-------------+
; f, p j2 H# i| cust_id | month | idx | to_preserve |& c2 A* W# E) a0 X/ i9 b& D
+---------+-------+-----+-------------+( H: x; @$ |% g- W3 T: t! Z
| c3 | 0 | 1 | 0 |* A8 B6 @+ V3 J2 C! k) `2 f% V
| c3 | 0 | 2 | 0 |
0 h& ^7 Z, L; e# y5 n, p| c3 | 100 | 3 | 1 |
' b& b7 t; r* w% T, T: y \9 i| c3 | 0 | 4 | 1 |+ X& [1 N9 j0 G- f" p8 C% p9 d
| c3 | 0 | 5 | 1 |0 v( a% a0 S( u0 l/ K' N
+---------+-------+-----+-------------+) U. \/ b) N- K4 }0 J4 B
该MAX(IIF(month=0,0,1)) OVER (ORDER BYidx)表达式确保从第一个非零开始的所有值都to_preserve设置为1。9 `* h% P- r5 `# r" ?
然后,它to_preserve使用标志选择值,并用于ROW_NUMBER提供一个值,该值可用于透视到正确的新列中。 |
|