Разделить строку URL с несколькими разделителями на несколько строк - PullRequest
0 голосов
/ 13 февраля 2020

Я хотел бы проанализировать строку URL-запроса в SQL Сервер в несколько столбцов следующим образом со следующим результатом:

plants=indoor,succulents&locations=ca,co,az&priceupto=100

Желаемый результат:

Result

Как мне go об этом? Любая идея будет оценена.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 13 февраля 2020

Добро пожаловать в переполнение стека! Ваша проблема стала немного сложнее после того, как вы добавили скриншот. Для дальнейшего использования укажите желаемые результаты при публикации, чтобы люди не усердно работали над предоставлением ответа, который вам не нужен [/ soapbox].

Во всяком случае, вот как вы можете справиться с этим, используя SPLIT_STRING обратите внимание на мои комментарии.

DECLARE @string VARCHAR(8000) = 'plants=indoor,succulents&locations=ca,co,az&priceupto=100';

WITH split AS 
(
  SELECT      s2.[value], f.Attrib
  FROM        STRING_SPLIT(@string,'&')                     AS s1
  CROSS APPLY (VALUES(CHARINDEX('=',s1.[value])))           AS dd(Idx)
  CROSS APPLY (VALUES(SUBSTRING(s1.[value],0,dd.Idx),
                      SUBSTRING(s1.[value],dd.Idx+1,8000))) AS f(Attrib,Txt)
  CROSS APPLY STRING_SPLIT(f.Txt,',')                       AS s2
)
SELECT 
  Plant      = pl.[value],  
  [Location] = lo.[value],
    Priceupto  = pr.[value]
FROM       split AS pl
CROSS JOIN split AS lo
CROSS JOIN split AS pr
WHERE      pl.Attrib = 'plants'
AND        lo.Attrib = 'locations'
AND        pr.Attrib = 'priceupto';
--ORDER BY   1,2,3 -- likely not required but returns items in the requested order if needed

FYI - для дальнейшего использования вы можете (добавив 4 пробела перед каждой строкой) сказать: «Вот результат, который я ищу:»

Plant         Location  Priceupto
------------- --------- ------------
indoor        ca        100
succulents    ca        100
indoor        co        100
succulents    co        100
indoor        az        100
succulents    az        100

Это работает намного лучше, чем скриншот, потому что мы можем копировать / вставлять значения.

0 голосов
/ 13 февраля 2020

Вы можете попробовать кое-что по этому поводу:

DECLARE @str VARCHAR(1000)='plants=indoor,succulents&locations=ca,co,az&priceupto=100';

SELECT CAST('<x content="' + REPLACE(REPLACE(REPLACE(@str,',','</y><y>'),'=','"><y>'),'&','</y></x><x content="') + '"</y></x>' AS XML);

Мы используем некоторые замены, чтобы преобразовать вашу строку в XML

<x content="plants">
  <y>indoor</y>
  <y>succulents</y>
</x>
<x content="locations">
  <y>ca</y>
  <y>co</y>
  <y>az</y>
</x>
<x content="priceupto">
  <y>100"</y>
</x>

Как использовать это

Проверьте это как ваш последний запрос

DECLARE @str VARCHAR(1000)='plants=indoor,succulents&locations=ca,co,az&priceupto=100';

SELECT A.plants.value('text()[1]','varchar(100)') AS Plant
      ,B.locations.value('text()[1]','varchar(100)') AS [Location]
      ,C.priceupto.value('text()[1]','varchar(100)') AS PriceUpTo
FROM (VALUES(CAST('<x content="' + REPLACE(REPLACE(REPLACE(@str,',','</y><y>'),'=','"><y>'),'&','</y></x><x content="') + '</y></x>' AS XML))) The(StringAsXml)
CROSS APPLY The.StringAsXml.nodes('/x[@content="plants"]/y') A(plants)
CROSS APPLY The.StringAsXml.nodes('/x[@content="locations"]/y') B(locations)
CROSS APPLY The.StringAsXml.nodes('/x[@content="priceupto"]/y') C(priceupto);

Результат

Plant   Location    PriceUpTo
indoor      ca      100
indoor      co      100
indoor      az      100
succulents  ca      100
succulents  co      100
succulents  az      100

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

Использование CROSS APPLY с .nodes() добавит список каждое значение ниже заданного XPath.
Это создаст каждый-с-каждым результат, аналогичный CROSS JOIN ing сетам.

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

SELECT A.plants.value('text()[1]','varchar(100)') AS Plant
      ,B.locations.value('text()[1]','varchar(100)') AS [Location]
      ,the.StringAsXml.value('(/x[@content="priceupto"]/y/text())[1]','varchar(100)') AS PriceUpTo
FROM (VALUES(CAST('<x content="' + REPLACE(REPLACE(REPLACE(@str,',','</y><y>'),'=','"><y>'),'&','</y></x><x content="') + '</y></x>' AS XML))) The(StringAsXml)
CROSS APPLY The.StringAsXml.nodes('/x[@content="plants"]/y') A(plants)
CROSS APPLY The.StringAsXml.nodes('/x[@content="locations"]/y') B(locations)
0 голосов
/ 13 февраля 2020

Было бы проще разделить на несколько строк; разделение на несколько столбцов утомительно: вам нужно заранее знать максимальное количество параметров (столбцов), которое вы ожидаете просто написать запрос (в противном случае вам понадобится Dynami c SQL).

Здесь простое решение, которое разбивает строки, используя string_split(); обратите внимание, что с этой функцией не существует возможного порядкового номера (ie нет гарантии, в котором будут сгенерированы строки заказа).

select t.url original_url, value param_value
from mytable t
cross apply string_split(t.url, '&') 

Предполагается, что URL хранится в столбце url таблицы * 1008. *.

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

select 
    t.url original_url, 
    left(value, charindex('=', value) - 1) param,
    right(value, len(value) - charindex('=', value)) val
from mytable t
cross apply string_split(t.url, '&') 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...