Разделить столбец на несколько столбцов в таблице SQL Server, но некоторые недопустимые значения не выровнены - PullRequest
0 голосов
/ 21 апреля 2019

Мне нужно разделить столбец на несколько столбцов в SQL Server 2012 (v11).

Мои данные:

 a_value
----------------------------------------------------------
 (6, 5, 1908, 650)
 (16, 21, 3002, 110)
 (-228,117,29,335,279,700,000,000,000,000,000,000,000,000)
 (-387,150,276,186,008)
 NULL

Большинство данных имеют 3 запятые (которые действительны)но некоторые из них нет.Для этих недопустимых значений я хочу поместить их в виде строки в другом столбце.

Я хочу:

 w1    w2    w3    w4       w5
---------------------------------------------------------------------------------------
 6     5     1908  650      NULL 
 16   21     3002  110      NULL
 NULL NULL   NULL  NULL     (-228,117,29,335,279,700,000,000,000,000,000,000,000,000)
 NULL NULL   NULL  NULL     (-387,150,276,186,008)
 NULL NULL   NULL  NULL     NULL

Мой запрос SQL:

SELECT 
    CASE 
       WHEN LEN(a_value) >= 9 
          THEN PARSENAME(REPLACE(substring(a_value, 1, LEN(a_value) -2), ',', '.'), 4)
          ELSE NULL
    END AS w1,
    CASE 
       WHEN LEN(a_value) >= 9 
          THEN PARSENAME(REPLACE(substring(a_value, 1, LEN(a_value) -2), ',', '.'), 3)
          ELSE NULL
    END AS w2,
    CASE 
       WHEN LEN(a_value) >= 9 
          THEN PARSENAME(REPLACE(substring(a_value, 1, LEN(a_value) -2), ',', '.'), 2)
          ELSE NULL
    END AS w3,
    CASE 
       WHEN LEN(window_pos_size) >= 9 
          THEN PARSENAME(REPLACE(substring(a_value, 1, LEN(a_value) -2), ',', '.'), 1)
          ELSE NULL
    END AS w4
FROM 
    my_tbl

Не работает.

Есть предложения по запросу SQL?

Ответы [ 3 ]

1 голос
/ 21 апреля 2019

Просто еще один вариант

Пример

Select B.*
      ,W5 = case when W4 is null then a_value end
 From YourTable A
 Outer Apply (
    Select W1 = ltrim(rtrim(xDim.value('/x[1]','varchar(100)')))
          ,W2 = ltrim(rtrim(xDim.value('/x[2]','varchar(100)')))
          ,W3 = ltrim(rtrim(xDim.value('/x[3]','varchar(100)')))
          ,W4 = ltrim(rtrim(xDim.value('/x[4]','varchar(100)')))
     From  (Select Cast('<x>' + replace(replace(replace(a_value,'(',''),')',''),',','</x><x>')+'</x>' as xml) as xDim) as A 
     Where xDim.value('/x[5]','varchar(100)') is null
 ) B 

Возвращает

enter image description here

0 голосов
/ 21 апреля 2019

Другой возможный подход заключается в подсчете запятых:

Ввод:

CREATE TABLE #Data (
   a_value varchar(max)
)
INSERT INTO #Data
   (a_value)
VALUES
   ('(6, 5, 1908, 650)'),
   ('(16, 21, 3002, 110)'),
   ('(-228,117,29,335,279,700,000,000,000,000,000,000,000,000)'),
   ('(-387,150,276,186,008)'),
   (NULL)

T-SQL:

SELECT 
    CASE 
       WHEN LEN(a_value) - LEN(REPLACE(a_value, ',', '')) = 3 
          THEN PARSENAME(REPLACE(SUBSTRING(a_value, 2, LEN(a_value) -2), ',', '.'), 4)
          ELSE NULL
    END AS w1,
    CASE 
       WHEN LEN(a_value) - LEN(REPLACE(a_value, ',', '')) = 3 
          THEN PARSENAME(REPLACE(SUBSTRING(a_value, 2, LEN(a_value) -2), ',', '.'), 3)
          ELSE NULL
    END AS w2,
    CASE 
       WHEN LEN(a_value) - LEN(REPLACE(a_value, ',', '')) = 3 
          THEN PARSENAME(REPLACE(SUBSTRING(a_value, 2, LEN(a_value) -2), ',', '.'), 2)
          ELSE NULL
    END AS w3,
    CASE 
       WHEN LEN(a_value) - LEN(REPLACE(a_value, ',', '')) = 3 
          THEN PARSENAME(REPLACE(SUBSTRING(a_value, 2, LEN(a_value) -2), ',', '.'), 1)
          ELSE NULL
    END AS w4,
    CASE 
       WHEN LEN(a_value) - LEN(REPLACE(a_value, ',', '')) = 3 
          THEN NULL
          ELSE a_value
    END AS w5
FROM 
    #Data

Выход:

----------------------------------------------------------------------------------------    
w1      w2      w3      w4      w5
----------------------------------------------------------------------------------------    
6       5       1908    650     NULL
16      21      3002    110     NULL
NULL    NULL    NULL    NULL    (-228,117,29,335,279,700,000,000,000,000,000,000,000,000)
NULL    NULL    NULL    NULL    (-387,150,276,186,008)
NULL    NULL    NULL    NULL    NULL
0 голосов
/ 21 апреля 2019

Я думаю, что это логика, которую вы хотите:

select (case when a_value not like '%,%,%,%,%'
             then PARSENAME(REPLACE(substring(a_value, 1, len(a_value) -2),',','.'),4)
        end) as w1,
       (case when a_value not like '%,%,%,%,%'
             then PARSENAME(REPLACE(substring(a_value, 1, len(a_value) -2),',','.'),3)
        end) as w2,
       (case when a_value not like '%,%,%,%,%'
             then PARSENAME(REPLACE(substring(a_value, 1, len(a_value) -2),',','.'),2)
        end) as w3,
       (case when a_value not like '%,%,%,%,%'
             then PARSENAME(REPLACE(substring(a_value, 1, len(a_value) -2),',','.'),1)
        end) as w4,
       (case when a_value like '%,%,%,%,%'
             then a_value
        end) as w5

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

Здесь - это дБ <> скрипка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...