Разделить один столбец на несколько столбцов - PullRequest
0 голосов
/ 04 сентября 2018

Я работаю над файлом отчета журнала аудита мощности. Файл содержит столбец AuditDate и содержит несколько столбцов. Мне нужно разделить этот столбец на несколько столбцов, используя sql.

Столбец имеет такие значения

AuditDate
------------
"{""Id"":""44de2468"",""RecordType"":20,""CreationTime"":""2018-08-03T12:30:34"",""Operation"":""ViewReport"",""OrganizationId"":""779558"",""UserType"":0,""UserKey"":""FFFA3DA"",""Workload"":""PowerBI"",""UserId"":""john@abc.com"",""ClientIP"":""9.5.3.26"",""UserAgent"":""Mozilla\/5.0 (Windows NT 10.0;"",""Activity"":""ViewReport"",""ItemName"":""Sales"",""WorkSpaceName"":""TeamITO"",""DatasetName"":""Sales1"",""ReportName"":""Sales1"",""WorkspaceId"":""e8eaa0ca"",""ObjectId"":""Sales1"",""DatasetId"":""4c5d-ad45-eb6546"",""ReportId"":""4cb0-99ad-de41b5160c47"",""IsSuccess"":true,""DatapoolRefreshScheduleType"":""None"",""DatapoolType"":""Undefined""}"

В основном мне нужно разбить этот столбец на

id     RecordType      CreationTime    Operaration     OrganizationID  UserType
------------------------------------------------------------------------------
44de2468    20     2018-08-03T12:30:34   ViewReport     779558               0

Может кто-нибудь помочь с запросом sql для этого?

Ответы [ 3 ]

0 голосов
/ 05 сентября 2018

Похоже, вы имеете дело с искаженным столбцом JSON. Эти двойные двойные кавычки беспокоят.

Если вы можете очистить форматирование, вы можете просто использовать функции JSON в своем запросе.

Сначала настройте данные (используя данные, которые вы указали в другой копии этого вопроса, ( Разделить значения столбцов на несколько столбцов ):

DECLARE @t TABLE 
(
  RecordType NVARCHAR(20)
  ,AuditDate NVARCHAR(MAX)
);
INSERT @t
  (
    RecordType
    ,AuditDate
  )
VALUES
  ('View', '{""Id"":""44de2468"",""Type"":20,""CreationDate"":""2018-08-23""}')
 ,('Edit', '{""Id"":""44de2467"",""Type"":40,""CreationDate"":""2018-08-24""}')
 ,('Print', '{""Id"":""44de2768"",""Type"":60,""CreationDate"":""2018-05-06""}')
 ,('Delete', '{""Id"":""44de2488"",""Type"":30,""CreationDate"":""2018-07-20""}');

Теперь очистите искаженные JSON, заменив двойные двойные кавычки одинарными двойными кавычками.

UPDATE @t
SET AuditDate = REPLACE(AuditDate,'""','"');

Проверка правильности JSON-файлов.

SELECT * FROM @t

--Results:
+------------+---------------------------------------------------------+
| RecordType |                        AuditDate                        |
+------------+---------------------------------------------------------+
| View       | {"Id":"44de2468","Type":20,"CreationDate":"2018-08-23"} |
| Edit       | {"Id":"44de2467","Type":40,"CreationDate":"2018-08-24"} |
| Print      | {"Id":"44de2768","Type":60,"CreationDate":"2018-05-06"} |
| Delete     | {"Id":"44de2488","Type":30,"CreationDate":"2018-07-20"} |
+------------+---------------------------------------------------------+

Затем используйте JSON_VALUE(), чтобы извлечь интересующие вас детали.

SELECT 
    RecordType
  , JSON_VALUE(AuditDate, '$.Id') AS [Id]
  , JSON_VALUE(AuditDate, '$.Type') AS [Type]
  , JSON_VALUE(AuditDate, '$.CreationDate') AS CreationDate
FROM @t

--Results
+------------+----------+------+--------------+
| RecordType |    Id    | Type | CreationDate |
+------------+----------+------+--------------+
| View       | 44de2468 |   20 | 2018-08-23   |
| Edit       | 44de2467 |   40 | 2018-08-24   |
| Print      | 44de2768 |   60 | 2018-05-06   |
| Delete     | 44de2488 |   30 | 2018-07-20   |
+------------+----------+------+--------------+
0 голосов
/ 05 сентября 2018

С SQL-Server 2016 это довольно просто. Есть довольно некоторая поддержка JSON. Ваша единственная проблема в том, что ваша строка неверна. Совершенно очевидно, что был механизм, удваивающий все внутренние кавычки (техника выхода).

Если это под вашим контролем, попробуйте изменить формат столбца на правильный JSON. Еще лучше, чтобы приложение для написания предоставило эти проверки в правильном формате JSON. По крайней мере, вы можете добавить второй столбец и использовать триггер для синхронизации. В крайнем случае вы можете использовать REPLACE для восстановления вашей строки:

REPLACE(REPLACE(REPLACE(@YourString,'"{','{'),'}"','}'),'""','"');

При большом количестве строк это может занять некоторое время ... Поэтому лучше поддерживать формат в надлежащем формате JSON.

Просто чтобы показать принципы:

DECLARE @YourString NVARCHAR(MAX)=N'"{""Id"":""44de2468"",""RecordType"":20,""CreationTime"":""2018-08-03T12:30:34"",""Operation"":""ViewReport"",""OrganizationId"":""779558"",""UserType"":0,""UserKey"":""FFFA3DA"",""Workload"":""PowerBI"",""UserId"":""john@abc.com"",""ClientIP"":""9.5.3.26"",""UserAgent"":""Mozilla\/5.0 (Windows NT 10.0;"",""Activity"":""ViewReport"",""ItemName"":""Sales"",""WorkSpaceName"":""TeamITO"",""DatasetName"":""Sales1"",""ReportName"":""Sales1"",""WorkspaceId"":""e8eaa0ca"",""ObjectId"":""Sales1"",""DatasetId"":""4c5d-ad45-eb6546"",""ReportId"":""4cb0-99ad-de41b5160c47"",""IsSuccess"":true,""DatapoolRefreshScheduleType"":""None"",""DatapoolType"":""Undefined""}"';

SET @YourString = REPLACE(REPLACE(REPLACE(@YourString,'"{','{'),'}"','}'),'""','"');

Теперь ваша строка будет выглядеть так:

{"Id":"44de2468","RecordType":20,"CreationTime":"2018-08-03T12:30:34","Operation":"ViewReport","OrganizationId":"779558","UserType":0,"UserKey":"FFFA3DA","Workload":"PowerBI","UserId":"john@abc.com","ClientIP":"9.5.3.26","UserAgent":"Mozilla\/5.0 (Windows NT 10.0;","Activity":"ViewReport","ItemName":"Sales","WorkSpaceName":"TeamITO","DatasetName":"Sales1","ReportName":"Sales1","WorkspaceId":"e8eaa0ca","ObjectId":"Sales1","DatasetId":"4c5d-ad45-eb6546","ReportId":"4cb0-99ad-de41b5160c47","IsSuccess":true,"DatapoolRefreshScheduleType":"None","DatapoolType":"Undefined"}

Этот запрос вернет все ваши столбцы в виде списка:

SELECT * 
FROM OPENJSON(@YourString);

Результат возвращает список с подсказкой типа (в то время как фактический тип «value» равен nvarchar):

+-----------------------------+-------------------------------+------+
| key                         | value                         | type |
+-----------------------------+-------------------------------+------+
| Id                          | 44de2468                      | 1    |
+-----------------------------+-------------------------------+------+
| RecordType                  | 20                            | 2    |
+-----------------------------+-------------------------------+------+
| CreationTime                | 2018-08-03T12:30:34           | 1    |
+-----------------------------+-------------------------------+------+
| Operation                   | ViewReport                    | 1    |
+-----------------------------+-------------------------------+------+
| OrganizationId              | 779558                        | 1    |
+-----------------------------+-------------------------------+------+
| UserType                    | 0                             | 2    |
+-----------------------------+-------------------------------+------+
| UserKey                     | FFFA3DA                       | 1    |
+-----------------------------+-------------------------------+------+
| Workload                    | PowerBI                       | 1    |
+-----------------------------+-------------------------------+------+
| UserId                      | john@abc.com                  | 1    |
+-----------------------------+-------------------------------+------+
| ClientIP                    | 9.5.3.26                      | 1    |
+-----------------------------+-------------------------------+------+
| UserAgent                   | Mozilla/5.0 (Windows NT 10.0; | 1    |
+-----------------------------+-------------------------------+------+
| Activity                    | ViewReport                    | 1    |
+-----------------------------+-------------------------------+------+
| ItemName                    | Sales                         | 1    |
+-----------------------------+-------------------------------+------+
| WorkSpaceName               | TeamITO                       | 1    |
+-----------------------------+-------------------------------+------+
| DatasetName                 | Sales1                        | 1    |
+-----------------------------+-------------------------------+------+
| ReportName                  | Sales1                        | 1    |
+-----------------------------+-------------------------------+------+
| WorkspaceId                 | e8eaa0ca                      | 1    |
+-----------------------------+-------------------------------+------+
| ObjectId                    | Sales1                        | 1    |
+-----------------------------+-------------------------------+------+
| DatasetId                   | 4c5d-ad45-eb6546              | 1    |
+-----------------------------+-------------------------------+------+
| ReportId                    | 4cb0-99ad-de41b5160c47        | 1    |
+-----------------------------+-------------------------------+------+
| IsSuccess                   | true                          | 3    |
+-----------------------------+-------------------------------+------+
| DatapoolRefreshScheduleType | None                          | 1    |
+-----------------------------+-------------------------------+------+
| DatapoolType                | Undefined                     | 1    |
+-----------------------------+-------------------------------+------+

А еще лучше, вы можете добавить предложение WITH как здесь:

SELECT * 
FROM OPENJSON(@YourString)
WITH 
(   
    Id             varchar(200)  '$.Id',  
    RecordType     int           '$.RecordType',  
    CreationTime   datetime      '$.CreationTime'
    --Add all your known columns here...
)

При этом вы набираете значения и бок о бок

+----------+------------+-------------------------+
| Id       | RecordType | CreationTime            |
+----------+------------+-------------------------+
| 44de2468 | 20         | 2018-08-03 12:30:34.000 |
+----------+------------+-------------------------+
0 голосов
/ 04 сентября 2018

Это довольно просто, все, что вам нужно, это строковый разделитель (AKA tokenizer). Если вы используете SQL 2016+, вы можете использовать STRING_SPLIT; если вы используете систему до 2016 года, вы можете использовать DelimitedSplit8K в 2005+ или DelimitedSplit8K_LEAD в 2012+. Решение будет выглядеть так:

DECLARE @AuditDate VARCHAR(8000) = 
'"{""Id"":""44de2468"",""RecordType"":20,""CreationTime"":""2018-08-03T12:30:34"",""Operation"":""ViewReport"",""OrganizationId"":""779558"",""UserType"":0,""UserKey"":""FFFA3DA"",""Workload"":""PowerBI"",""UserId"":""john@abc.com"",""ClientIP"":""9.5.3.26"",""UserAgent"":""Mozilla\/5.0 (Windows NT 10.0;"",""Activity"":""ViewReport"",""ItemName"":""Sales"",""WorkSpaceName"":""TeamITO"",""DatasetName"":""Sales1"",""ReportName"":""Sales1"",""WorkspaceId"":""e8eaa0ca"",""ObjectId"":""Sales1"",""DatasetId"":""4c5d-ad45-eb6546"",""ReportId"":""4cb0-99ad-de41b5160c47"",""IsSuccess"":true,""DatapoolRefreshScheduleType"":""None"",""DatapoolType"":""Undefined""}"'

SELECT 
  Id             = MAX(CASE split.attrib WHEN 'ID'             THEN split.val END),
  RecordType     = MAX(CASE split.attrib WHEN 'RecordType'     THEN split.val END),
  CreationTime   = MAX(CASE split.attrib WHEN 'CreationTime'   THEN split.val END),
  Operation      = MAX(CASE split.attrib WHEN 'Operation'      THEN split.val END),
  OrganizationId = MAX(CASE split.attrib WHEN 'OrganizationId' THEN split.val END),
  UserType       = MAX(CASE split.attrib WHEN 'UserType'       THEN split.val END)
FROM
(
  SELECT      attrib = REPLACE(REPLACE(SUBSTRING(split.value, 1, mid.point-1),'{',''),'"',''),
              val    = REPLACE(REPLACE(SUBSTRING(split.value, mid.point+1, 8000),'{',''),'"','')
  FROM        STRING_SPLIT(@AuditDate,',') AS split
  CROSS APPLY (VALUES(CHARINDEX(':', split.value))) AS mid(point)
  WHERE       REPLACE(REPLACE(SUBSTRING(split.value, 1, mid.point-1),'{',''),'"','') IN
                ('id','RecordType','CreationTime','Operation','OrganizationID','UserType')
) AS split;

Результаты:

Id         RecordType  CreationTime          Operation   OrganizationId  UserType
---------- ----------- --------------------- ----------- --------------- ---------
44de2468   20          2018-08-03T12:30:34   ViewReport  779558          0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...