2017-06-20 63 views
6

Potrzebuję przesunąć dane (kolumny) na lewą stronę, jeśli pierwsze kolumny (lewa strona kolumny) mają wartość 0, a NULL należy dodać w kolumnach po prawej stronie. Po znalezieniu niezerowej wartości w kolumnach, wartość 0 w późniejszej kolumnie powinna pozostać taka, jaka jest. DaneMS SQL 2012: W kolumnie SQL Shift po lewej stronie, jeśli kolumna zawiera 0

wejściowe: -

cust_id month1 month2 month3 month4 month5 
c1  100  200  300  400  500 
c2  0  0  50  250  350 
c3  0  0  100  0  0 
c4  100  0  100  0  500 
c5  0  0  0  0  0 

Oczekiwany wynik wyjściowy: -

cust_id month1 month2 month3 month4 month5 
c1  100  200  300  400  500 
c2  50  250  350  NULL NULL 
c3  100  0  0  NULL NULL 
c4  100  0  100  0  500 
c5  NULL NULL NULL NULL NULL 

Jeden obejście statyczne mogą być:

IF month1=0 and month2=0 and month3=0 and month4=0 and month5=0 
THEN INSERT INTO TABLE output_table AS SELECT cust_id,'NULL','NULL','NULL','NULL','NULL' FROM input_table 

IF month1=0 and month2=0 and month3=0 and month4=0 and month5 != 0 
THEN INSERT INTO TABLE output_table AS SELECT cust_id,month5,'NULL','NULL','NULL','NULL' FROM input_table 

IF month1=0 and month2=0 and month3=0 and month4 != 0 and month5 != 0 
THEN INSERT INTO TABLE output_table AS SELECT cust_id,month4,month5,'NULL','NULL','NULL' FROM input_table 

IF month1=0 and month2=0 and month3 !=0 and month4 != 0 and month5 != 0 
THEN INSERT INTO TABLE output_table AS SELECT cust_id,month3,month4,month5,'NULL','NULL' FROM input_table 

IF month1 != 0 and month2 != 0 and month3 !=0 and month4 != 0 and month5 != 0 
THEN INSERT INTO TABLE output_table AS SELECT cust_id,month1,month2,month3,month4,month5,'NULL' FROM input_table 

Mogę znaleźć poniżej odprowadzenia w przepełnieniu stosu, które wyjaśnia przesunięcie kolumn w lewo, jeśli wszystkie kolumny mają wartość zerową. Ale zastępuje wszystkie NULL (nawet jeśli NULL przychodzi po każdej niezerowej/nie zerowej wartości).

move cells left in sql if left contains null and right contains value

Mam zamiar zbudować dynamiczne rozwiązanie, które mogą obsługiwać nowe kolumny gdy dane miesiąc do miesiąca zostanie dodana.

Baza danych jest MS SQL Server 2012.

Szybkie zapytania SQL, aby przygotować dane: -

CREATE TABLE input_table(
     cust_id char(5), 
     month1 int, 
     month2 int, 
     month3 int, 
     month4 int, 
     month5 int 
); 


INSERT INTO input_table VALUES 
('c1',100,200,300,400,500), 
('c2',0,0,50,250,350), 
('c3',0,0,100,0,0), 
('c4',100,0,100,0,500), 
('c5',0,0,0,0,0); 
+1

Czy zdenormalizowałeś swoje dane jako wstępny krok specjalnie dla tej operacji? Jeśli Twoje dane mają postać kolumn dla cust_id, month_number i value, będą łatwiejsze w użyciu. Jeśli dane podstawowe znajdują się w zdormowanej formie, którą pokazujesz, możesz normalizować je tylko dla tej operacji. –

+0

co zamierzasz zrobić z danymi po tym, jak dostaniesz je w tym formacie? i czy możesz je sformatować za pomocą https://ozh.github.io/ascii-tables/ – scsimon

+0

@scsimon Utworzono tabele o/p i oczekiwane o/p w czytelnym formacie. Jest to wymagane w przypadku ML Algo. – XEngineer

Odpowiedz

1

ten powinien robić to, co trzeba (demo)

SELECT i.cust_id, 
     oa.* 
FROM input_table i 
     OUTER APPLY (SELECT pvt.* 
        FROM (SELECT month, 
            col = CONCAT('month', ROW_NUMBER() OVER (ORDER BY idx)) 
          FROM (SELECT month, 
              idx, 
              to_preserve = MAX(IIF(month=0,0,1)) OVER (ORDER BY idx) 
            FROM (VALUES (1, month1), 
                (2, month2), 
                (3, month3), 
                (4, month4), 
                (5, month5)) V(idx, month)) unpvt 
          WHERE to_preserve = 1) t 
          PIVOT (MAX(month) FOR col IN (month1, month2, month3, month4, month5)) pvt 
          ) oa 

To unpivots kolumna wartości wiersz na raz.

Przykładowo C3 skończy nieprzestawne do

+---------+-------+-----+-------------+ 
| cust_id | month | idx | to_preserve | 
+---------+-------+-----+-------------+ 
| c3  |  0 | 1 |   0 | 
| c3  |  0 | 2 |   0 | 
| c3  | 100 | 3 |   1 | 
| c3  |  0 | 4 |   1 | 
| c3  |  0 | 5 |   1 | 
+---------+-------+-----+-------------+ 

Wyrażenie MAX(IIF(month=0,0,1)) OVER (ORDER BY idx) zapewnia, że ​​wszystkie wartości w pierwszym niezerowym i następne mają to_preserve zestaw do 1.

Następnie wybiera wartości z flagą to_preserve i używa ROW_NUMBER, aby podać wartość, która może być użyta do przestawienia do właściwej nowej kolumny.