Как преобразовать первую строку как имя столбца? - PullRequest
1 голос
/ 02 мая 2019

Надеюсь, у вас все хорошо.Я хотел бы получить вашу помощь в решении задачи преобразования данных, которая у меня есть.Я хотел бы преобразовать первую строку таблицы в имя столбца

Я работаю на SQL Server Azure и получаю ежедневные данные от другого сервиса.

Этот сервис загружает таблицу, котораятой же формы.

enter image description here

, и я хотел бы преобразовать данные таким же образом

enter image description here

У вас есть идеи, как это сделать?

Ответы [ 2 ]

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

Способ решить эту проблему с помощью небольшой динамической магии SQL:

Сначала создайте и заполните образец таблицы ( Пожалуйста, спасите нас, таким образом, шаг в ваших будущих вопросах):

DECLARE @T As Table
(
    Row_num int,
    Line nvarchar(4000)
);

INSERT INTO @T (Row_Num, Line) VALUES
(1, 'Col1;Col2;Col3'),
(2, 'Val1;Val2;Val3'),
(3, 'Value1;Value2;Value1'),
(4, 'Val A; val B;Val A'),
(5, 'Value A; Value B;Value C');

Затем создайте запрос на объединение всех, который выбирает значения из каждой строки, кроме первой, заменив точку с запятой (;) запятой (,), окруженную апострофами ('). Добавьте апостроф до и после строки (это означает, что мы обрабатываем все данные как строки):

DECLARE @Sql nvarchar(max) = '';

SELECT @Sql += 'UNION ALL SELECT '''+ REPLACE(Line, ';', ''',''') + ''' '
FROM @T 
WHERE Row_Num > 1;

Затем используйте stuff для замены первого UNION ALL объявлением общего табличного выражения, указав имена столбцов в самом объявлении. Обратите внимание, что здесь нам больше не нужны апострофы, только для того, чтобы заменить точку с запятой на запятую:

SELECT @Sql = STUFF(@Sql, 1, 10, 'WITH CTE('+ REPLACE(Line, ';', ',') +') AS (') + ') SELECT * FROM CTE'
FROM @T 
WHERE Row_Num = 1;

Наконец, выполните sql:

EXEC(@Sql)

Результаты:

Col1        Col2        Col3
Val1        Val2        Val3
Value1      Value2      Value1
Val A        val B      Val A
Value A      Value B    Value C

Вы можете увидеть живое демо на rextester.

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

Другой возможный подход - преобразовать ваши текстовые данные в действительные массивы JSON, а затем использовать OPENJSON () с явной схемой и динамическим оператором.

Рабочий пример:

Ввод:

CREATE TABLE #Data (
   RowNum int,
   Line nvarchar(max)
)
INSERT INTO #Data
   (RowNum, Line)
VALUES
   (1, 'ColumnA;ColumnB;ColumnC'),
   (2, 'ValueA1;ValueB1;ValueC1'),
   (3, 'ValueA2;ValueB2;ValueC2'),
   (4, 'ValueA3;ValueB3;ValueC3'),
   (5, 'ValueA4;ValueB4;ValueC4'),
   (6, 'ValueA5;ValueB5;ValueC5')

T-SQL:

-- Explicit schema generation
DECLARE @schema nvarchar(max)
SELECT @schema = STUFF((
   SELECT CONCAT(N',', j.[value], N' nvarchar(max) ''$[', j.[key], N']''')
   FROM #Data d
   CROSS APPLY OPENJSON(CONCAT(N'["', REPLACE(d.Line, ';', '","'), N'"]')) j
   WHERE d.RowNum = 1
   FOR XML PATH('')
), 1, 1, N'')

-- Dymanic statement
DECLARE @stm nvarchar(max)
SET @stm = CONCAT(
   N'SELECT j.* FROM #Data d ',
   N'CROSS APPLY OPENJSON(CONCAT(N''[["'', REPLACE(d.Line, '';'', ''","''), N''"]]'')) ',
   N'WITH (',
   @schema,
   N') j WHERE d.RowNum > 1'
)

-- Execution
EXEC sp_executesql @stm

Ввод:

-----------------------
ColumnA ColumnB ColumnC
-----------------------
ValueA1 ValueB1 ValueC1
ValueA2 ValueB2 ValueC2
ValueA3 ValueB3 ValueC3
ValueA4 ValueB4 ValueC4
ValueA5 ValueB5 ValueC5

Пояснения:

Основная часть заключается в преобразовании данных каждой строки в действительные массивы JSON.Количество столбцов может быть различным.

Данные из первой строки будут использоваться для явного создания схемы, а значения ColumnA;ColumnB;ColumnC преобразуются в ["ColumnA","ColumnB","ColumnC"].Значения из последующих строк ValueA1;ValueB1;ValueC1 преобразуются в [["ValueA1","ValueB1","ValueC1"]].

Следующие простые примеры демонстрируют, как OPENJSON() возвращает данные со стандартной и явной схемой:

Со стандартной схемой:

DECLARE @json nvarchar(max)
SET @json = '["ValueA1", "ValueB1", "ValueC1"]'
SELECT *
FROM OPENJSON(@json) 

Вывод для схемы по умолчанию:

----------------
key value   type
----------------
0   ValueA1 1
1   ValueB1 1
2   ValueC1 1

С явной схемой:

SET @json = '[["ValueA1", "ValueB1", "ValueC1"]]'
SELECT *
FROM OPENJSON(@json) 
WITH (
   ColumnA nvarchar(max) '$[0]',
   ColumnB nvarchar(max) '$[1]',
   ColumnC nvarchar(max) '$[2]'
)

Вывод для явной схемы:

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