Сводный sql при наличии символа

Я хотел бы иметь запрос, который всегда приводил бы к созданию нового столбца, когда я нахожу символ '-'

Пример:

WITH Test as (
SELECT 'Robert - Plant' as name union all
SELECT 'Mary - Elizabeth -Smith' as name union all
SELECT 'Cristian - Lord Gray, Tyson' as name
)

SELECT Name
FROM Test

Должен быть:

Name1, Name 2, Name 3, name4
Robert, Plant, Null, Null
Mary, Elizabeth, Smith, Null
Cristian, Lord, Gray, Tyson

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

Damien_The_Unbeliever 10.08.2018 16:50

Увидел ваш второй запрос с одним разделителем. См. Отредактировать в моем ответе более чистый пример.

John Cappelletti 10.08.2018 20:38
0
2
47
1

Ответы 1

Cross Apply B создаст строку «CleanString», разделенную пробелами.

Cross Apply C проанализирует чистую строку

Пример

WITH Test as (
SELECT 'Robert - Plant' as name union all
SELECT 'Mary - Elizabeth -Smith' as name union all
SELECT 'Cristian - Lord Gray, Tyson' as name
)


Select Name
      ,C.*
 From  Test A
 Cross Apply (values (ltrim(rtrim(replace(replace(replace(replace(replace(Name,'-',' '),',',' '),' ','†‡'),'‡†',''),'†‡',' ')))) ) B(CleanString)
 Cross Apply (
                Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
                      ,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
                      ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
                      ,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
                      ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
                From  (Select Cast('<x>' + replace(CleanString,' ','</x><x>')+'</x>' as xml) as xDim) as A 
             ) C

Возврат

Name                            Pos1        Pos2        Pos3    Pos4    Pos5
Robert - Plant                  Robert      Plant       NULL    NULL    NULL
Mary - Elizabeth -Smith         Mary        Elizabeth   Smith   NULL    NULL
Cristian - Lord Gray, Tyson     Cristian    Lord        Gray    Tyson   NULL

EDIT - Saw your 2nd Qustion with a single delimter

WITH TEST AS
  (SELECT 'AAAA - BBBBB - CCCC- DDDD' AS Name
   UNION ALL SELECT 'EEEE - GGGGG - FFFF' AS Name
   UNION ALL SELECT 'EEEE - RRRR -' AS Name
   UNION ALL SELECT 'LLLL - WWWW - IIII- TTTT' AS Name
   UNION ALL SELECT 'QQQQ' AS Name
  )
SELECT A.Name
      ,B.*
 FROM TEST A
 Cross Apply (
                Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
                      ,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
                      ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
                      ,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
                      ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
                From  (Select Cast('<x>' + replace(Name,'-','</x><x>')+'</x>' as xml) as xDim) as B1 
             ) B

Другие вопросы по теме