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

Я пытаюсь создать таблицу фактов с сервером SQL.В настоящее время это выглядит так:

[Item]  [Variant Descr.] [Variant Order] [Dim_Colour] [Dim_Size] [Dim_Style]
----------------------------------------------------------------------------
01         NAVY/44        COLOUR/SIZE     NULL         NULL       NULL
02         BLACK/S4       COLOUR/STYLE    NULL         NULL       NULL

Мне нужно разделить строку в [Вариант описания] и вставить части в правильный столбец Dim_, чтобы таблица в конечном итоге выглядела так:

[Item]  [Variant Descr.] [Variant Order] [Dim_Colour] [Dim_Size] [Dim_Style]
----------------------------------------------------------------------------
01         NAVY/44        COLOUR/SIZE     NAVY         44       NULL
02         BLACK/S4       COLOUR/STYLE    BLACK        NULL     S4

Проблема в том, что части [Порядок вариантов] и количество частей [Описание вариантов] могут различаться для каждой строки.Поэтому мне нужно сделать что-то вроде:

  1. Получить строку перед '/' в [Вариант описания]
  2. Получить строку перед '/' в [Порядок вариантов]
  3. Вставить первое значение в столбец, заданный вторым значением
  4. Сделайте это для всех частей [Описание варианта]
  5. Сделайте это для каждой строки таблицы

Я уже пытался решить эту проблему с помощью определяемой пользователем функции, но обнаружил, что не могу использовать динамический SQL в UDF.

Любая помощь будет принята с благодарностью

Ура!

Ответы [ 4 ]

1 голос
/ 27 мая 2019

Один из возможных подходов - разделить тексты в столбцах [Вариант описания] и [Порядок вариантов] и обновить таблицу динамическим оператором. Хотя использование STRING_SPLIT() является первым выбором, начиная с SQL Server 2016, в этом случае эта функция не является опцией, поскольку порядок подстрок не гарантируется. Рабочим решением является использование OPENJSON() - значения столбцов преобразуются в действительный объект JSON (например, 'NAVY/44' переводится в '["NAVY", "44"]'), а подстроки извлекаются с использованием OPENJSON().

Введите:

CREATE TABLE #Data (
   [Item] varchar(10),  
   [Variant Descr.] varchar(50), 
   [Variant Order] varchar(50), 
   [Dim_Colour] varchar(50),   
   [Dim_Size] varchar(50),  
   [Dim_Style] varchar(50)
)
INSERT INTO #Data 
   ([Item], [Variant Descr.], [Variant Order], [Dim_Colour], [Dim_Size], [Dim_Style])
VALUES
   ('01', 'NAVY/44',    'COLOUR/SIZE',       NULL, NULL, NULL),
   ('02', 'BLACK/S4',   'COLOUR/STYLE',      NULL, NULL, NULL),
   ('03', 'NAVY/44/S4', 'COLOUR/SIZE/STYLE', NULL, NULL, NULL),
   ('04', 'GREEN',      'COLOUR',            NULL, NULL, NULL)

T-SQL:

-- Dynamic statement
DECLARE @stm nvarchar(max) = N''
SELECT @stm = @stm + 
   N'UPDATE #Data ' +
   N'SET ' + 
   QUOTENAME('Dim_' + j1.[value]) +
   N' = ''' +
   j2.[value] +
   N''' WHERE Item = ''' +
   d.Item +
   N'''; '
FROM #Data d
CROSS APPLY OPENJSON(CONCAT('["', REPLACE([Variant Order], '/', '","'), '"]')) j1 
CROSS APPLY OPENJSON(CONCAT('["', REPLACE([Variant Descr.], '/', '","'), '"]')) j2
WHERE j1.[key] = j2.[key]

-- Execution and output
EXEC (@stm)
SELECT *
FROM #Data

Выход:

-----------------------------------------------------------------------------
Item    Variant Descr.  Variant Order     Dim_Colour    Dim_Size    Dim_Style
-----------------------------------------------------------------------------
01      NAVY/44         COLOUR/SIZE       NAVY          44  
02      BLACK/S4        COLOUR/STYLE      BLACK                     S4
03      NAVY/44/S4      COLOUR/SIZE/STYLE NAVY          44          S4
04      GREEN           COLOUR            GREEN     
0 голосов
/ 27 мая 2019

А вот и полностью обобщенный подход, чтобы разделить это (спасибо Жорову за MCVE!)агрегация или PIVOT.

Идея вкратце:

Я использую приведение к XML, чтобы позволить достичь фрагмента по его позиции.Кроме того, я использую CROSS APPLY вместе с ROW_NUMBER, который будет возвращать список чисел в зависимости от количества фрагментов в текущем ряду.Этот номер теперь используется в sql:column() для чтения подходящих фрагментов рядом .

0 голосов
/ 27 мая 2019

Вы можете получить требуемый результат по -

select [item] ,
      [variant descr],[variant order],
      left([variant descr],charindex('/', [variant descr]) - 1) AS [Dim_Colour],
      CASE WHEN [variant order] like '%/SIZE' THEN SUBSTRING([variant descr], CHARINDEX('/', [variant descr]) +1, 100)
       ELSE '' END  AS [Dim_Size],
      CASE WHEN [variant order] like '%/STYLE' THEN SUBSTRING([variant descr], CHARINDEX('/', [variant descr]) +1, 100)
       ELSE '' END  AS [Dim_Style]
    from your_table_name
0 голосов
/ 27 мая 2019

Попробуйте

IF OBJECT_ID('tempdb..#temp')IS NOT NULL
DROP TABLE #temp

CREATE TABLE #temp (
            [Item] INT,  
            [Variant Descr.] VARCHAR(100),
            [Variant Order] VARCHAR(100) ,
            [Dim_Colour] VARCHAR(100),
            [Dim_Size]INT ,
            [Dim_Style]  VARCHAR(100)
            )

INSERT INTO  #temp
SELECT 01,'NAVY/44' ,'COLOUR/SIZE' ,NULL,NULL,NULL UNION ALL
SELECT 02,'BLACK/S4','COLOUR/STYLE',NULL,NULL,NULL

SELECT * FROM #temp

UPDATE o 
SET     o.[Dim_Colour]  = dt.Dim_Colour, 
        o.Dim_Size = dt.Dim_Size,
        o.Dim_Style = dt.Dim_Style
FROM #temp o
INNER JOIN
(    

SELECT [Item],  [Variant Descr.], [Variant Order] ,
            SUBSTRING([Variant Descr.],0,CHARINDEX('/',[Variant Descr.])) AS [Dim_Colour]   
           ,CASE WHEN ISNUMERIC(SUBSTRING([Variant Descr.],CHARINDEX('/',[Variant Descr.])+1,LEN ([Variant Descr.]))) = 1 AND [Variant Order] = 'COLOUR/SIZE'   
                  THEN SUBSTRING([Variant Descr.],CHARINDEX('/',[Variant Descr.])+1,LEN ([Variant Descr.]))
                  ELSE NULL END AS [Dim_Size]
           ,CASE WHEN ISNUMERIC(SUBSTRING([Variant Descr.],CHARINDEX('/',[Variant Descr.])+1,LEN ([Variant Descr.]))) <> 1 AND [Variant Order] ='COLOUR/STYLE'
                  THEN SUBSTRING([Variant Descr.],CHARINDEX('/',[Variant Descr.])+1,LEN ([Variant Descr.]))
                  ELSE NULL END AS [Dim_Style]
      FROM  #temp i
)dt ON dt.[Item] = o.[Item]

SELECT * FROM  #temp 

Результат

Item    Variant Descr.  Variant Order       Dim_Colour  Dim_Size    Dim_Style
------------------------------------------------------------------------------
1       NAVY/44         COLOUR/SIZE            NAVY         44        NULL
2       BLACK/S4        COLOUR/STYLE           BLACK       NULL       S4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...