расщепление строк легко, есть множество примеров.Самое сложное здесь - соединить фрагменты через их положение.Мое предложение использует возможности XML для нацеливания на элемент по его позиции:
DECLARE @tbl TABLE(ID INT, product VARCHAR(100) , quantity VARCHAR(100) )
INSERT INTO @tbl VALUES
(1 ,'A|B|C' , '1|2|3')
,(2 ,'X|Y|Z' , '7|8|9');
- это запрос
WITH CastedToXML AS
(
SELECT *
,CAST('<x>' + REPLACE(product,'|','</x><x>') + '</x>' AS XML) AS ProductXml
,CAST('<x>' + REPLACE(quantity,'|','</x><x>') + '</x>' AS XML) AS QuantityXml
FROM @tbl
)
SELECT *
,ProductXml.value('/x[sql:column("Nmbr")][1]','nvarchar(10)') AS ProductAtPosition
,QuantityXml.value('/x[sql:column("Nmbr")][1]','int') AS QuantityAtPosition
FROM CastedToXML
--Create a set of running numbers (spt_values is just a pre-filled table with many rows)
CROSS APPLY (SELECT TOP(CastedToXML.ProductXml.value('count(/x)','int'))
ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM master..spt_values) AS Tally(Nmbr);
результат
+----+------+-------------------+--------------------+
| ID | Nmbr | ProductAtPosition | QuantityAtPosition |
+----+------+-------------------+--------------------+
| 1 | 1 | A | 1 |
+----+------+-------------------+--------------------+
| 1 | 2 | B | 2 |
+----+------+-------------------+--------------------+
| 1 | 3 | C | 3 |
+----+------+-------------------+--------------------+
| 2 | 1 | X | 7 |
+----+------+-------------------+--------------------+
| 2 | 2 | Y | 8 |
+----+------+-------------------+--------------------+
| 2 | 3 | Z | 9 |
+----+------+-------------------+--------------------+
Некоторое объяснение:
приведение к xml переводит ваш A|B|C
в
<x>A</x>
<x>B</x>
<x>C</x>
Этот список объединяется с набором номеров, созданным на лету с использованием счетчика <x>
как предел TOP
.
Теперь легко выбрать <x>
из вашего XML по позиции.
Попробуйте!
ОБНОВЛЕНИЕ:Неуникальные идентификаторы
DECLARE @tbl TABLE(ID INT, product VARCHAR(100) , quantity VARCHAR(100) )
INSERT INTO @tbl VALUES
(1 ,'A|B|C' , '1|2|3')
,(2 ,'X|Y|Z' , '7|8|9')
,(3 ,'a|b|c' , '7|8|9')
,(2 ,'D|e|f' , '7|8|9')
;
--This is the query
WITH CastedToXML AS
(
SELECT *
,ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID) AS RowIndex
,CAST('<x>' + REPLACE(product,'|','</x><x>') + '</x>' AS XML) AS ProductXml
,CAST('<x>' + REPLACE(quantity,'|','</x><x>') + '</x>' AS XML) AS QuantityXml
FROM @tbl
)
SELECT *
,ProductXml.value('/x[sql:column("Nmbr")][1]','nvarchar(10)') AS ProductAtPosition
,QuantityXml.value('/x[sql:column("Nmbr")][1]','int') AS QuantityAtPosition
FROM CastedToXML
--Create a set of running numbers (spt_values is just a pre-filled table with many rows)
CROSS APPLY (SELECT TOP(CastedToXML.ProductXml.value('count(/x)','int'))
ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM master..spt_values) AS Tally(Nmbr);