Есть ли более эффективный способ скольжения столбцов, чем поворот таблицы или использование XML и узлов - PullRequest
0 голосов
/ 16 октября 2019

Мне было интересно, есть ли другие методы для разделения столбцов или гораздо лучшие методы, чем эти два

Я собираюсь поместить некоторый код, чтобы мы могли говорить на одном языке

--CREATING TABLE
CREATE TABLE BOOKS(
ID VARCHAR(MAX) NULL
) 
/*
  BOOKS 
  PRODUCTID, NAME, PAGES, WEIGHT, SIZE, TYPE
*/
INSERT INTO BOOKS (ID)
VALUES('B001,INTRODUCTION TO SQL,500,100G,MID,TECH')
      ,('B002,ADVANCED SQL SERVER PRACTICES,200,200G,BIG,TECH')
      ,('B003,SQL SERVER PERFORMANCE,1000,500G,BIG,TECH')
      ,('B004,SQL SERVER MANUAL,50,30G,SMALL,TECH')
          ,('B004,SQL SERVER MANUAL,50,30G,SMALL,TECH')

Это будет моя демонстрационная таблица, как вы можете видеть, у меня есть таблица с разделенными запятыми значениями

Для разделения этих значений я собираюсь использовать сводку в сочетании с CTE

/*PIVOTING TABLE, ASIGNING A RN TO COLUMNS AND GETTING BACK VALUES*/
WITH C AS(
SELECT ID
      ,value 
      ,ROW_NUMBER() OVER(PARTITION BY ID ORDER BY (SELECT NULL)) as rn
FROM BOOKS BO
    CROSS APPLY STRING_SPLIT(ID, ',') AS BK
)
SELECT ID
      ,[1] AS PRODUCTID
      ,[2] AS NAME
      ,[3] AS PAGES
      ,[4] AS WEIGHT
      ,[5] AS SIZE
      ,[6] AS TYPE
FROM C
PIVOT(
    MAX(VALUE)
    FOR RN IN([1],[2],[3],[4],[5],[6])  
) as PVT

Это работаетхорошо, но в этом случае порядок строк, которые он возвращает, не гарантируется (например, 1,2,3,4). column1 = 1, column2 = 3 column3 = 2 column4 = 4, и я ожидаю получить 1,2,3,4. Другой хорошо известен здесь в stackoverflow с использованием XML и узлов

Другойодин из них хорошо известен здесь в stackoverflow с использованием XML и узлов

SELECT DISTINCT
    S.a.value('(/H/r)[1]', 'VARCHAR(100)') AS PRODUCTID
   ,S.a.value('(/H/r)[2]', 'VARCHAR(100)')  AS NAME
   , S.a.value('(/H/r)[3]', 'VARCHAR(100)') AS PAGES
   , S.a.value('(/H/r)[4]', 'VARCHAR(100)') AS WEIGHT
   , S.a.value('(/H/r)[5]', 'VARCHAR(100)') AS SIZE
   , S.a.value('(/H/r)[6]', 'VARCHAR(100)') AS TYPE
FROM
(
SELECT *,CAST (N'<H><r>' + REPLACE(ID, ',', '</r><r>')  
               + '</r></H>' AS XML) AS [vals]
FROM BOOKS) d 
CROSS APPLY d.[vals].nodes('/H/r') S(a) 

Также он работает, как и ожидалось, но не поймите меня неправильно, это сложно объяснить и немного сбить с толку, если вы не вышеначальный уровень.

Какие есть еще лучшие способы разделения столбцов в sql server, реализует ли Microsoft для этого новую функцию или вы знаете другой способ сделать это?

Ответы [ 2 ]

1 голос
/ 16 октября 2019

Если 2016+, еще одним вариантом является JSON.

JSON, кажется, превосходит XML, особенно в «Выбрать фрагмент» и «Выбрать значение» ( ref )

Пример dbFiddle

Select B.* 
 From BOOKS A
 Cross Apply (
               Select Pos1= JSON_VALUE(J,'$[0]')
                     ,Pos2= JSON_VALUE(J,'$[1]')
                     ,Pos3= JSON_VALUE(J,'$[2]')
                     ,Pos4= JSON_VALUE(J,'$[3]')
                     ,Pos5= JSON_VALUE(J,'$[4]')
                     ,Pos6= JSON_VALUE(J,'$[5]')
                From (values ('["'+replace(replace(ID,'"','\"'),',','","')+'"]'))A(J)
             ) B
1 голос
/ 16 октября 2019

Лично мой метод заключается в том, чтобы обработать значение как элемент с разделителями, а затем повернуть его с помощью кросс-таблицы. Так как порядковая позиция важна, а STRING_SPLIT не гарантирует этого, тогда DelimitedSplit8k_LEAD - гораздо лучший вариант здесь:

SELECT MAX(CASE DS.ItemNumber WHEN 1 THEN NULLIF(DS.Item,'') END) AS PRODUCTID,
       MAX(CASE DS.ItemNumber WHEN 2 THEN NULLIF(DS.Item,'') END) AS [NAME],
       MAX(CASE DS.ItemNumber WHEN 3 THEN NULLIF(DS.Item,'') END) AS PAGES,
       MAX(CASE DS.ItemNumber WHEN 4 THEN NULLIF(DS.Item,'') END) AS WEIGHT,
       MAX(CASE DS.ItemNumber WHEN 5 THEN NULLIF(DS.Item,'') END) AS SIZE,
       MAX(CASE DS.ItemNumber WHEN 6 THEN NULLIF(DS.Item,'') END) AS [TYPE]
FROM dbo.BOOKS B
     CROSS APPLY dbo.DelimitedSplit8K_LEAD(B.ID,',') DS
GROUP BY B.ID;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...