Split SQL character field to split columns
We have a database with data from our ERP, which is not that flexible, and we use this data to create reports in SSRS. I now have a price column for our articles / products which are very poorly formatted by ERP designers. The data is stored using "type" -identifier, the ones that cause problems are:
1 and 5: scaled ==> 2 lines/rows separated by ASCII char(9) and ASCII char(13) followed by char(10) for the second line.
As an example, this is one field:
11 999999999
16,9 11,154
This is another example:
99 1049 999999999
2 1,32 0,8
Line 1 is always QP, line 2 is always SP. I edited this to be clearer because the previous view was causing confusion. The number of char (9) -columns is variable, but the maximum is 3, so some may be 2. I am having problems splitting the second and sometimes the third column and splitting the second row into columns. The new table should be formatted as follows.
ID identifier QP1 SP1 QP2 SP2 QP3 SP3
The fields which are used are 'id', 'SPtype' ==>identifier, 'vk1'==>contains the prizes; and the table is 'DW_D_PRODUCT'.
Can anyone provide me with an efficient T-SQL. To deal with this problem. A stored procedure might be preferable, so it must run every night to update the prizes in the tables.
source to share
While it is not clear what the expected result is, I want to share with you the function I use when I have to deal with records as fields:
CREATE FUNCTION [dbo].[SplitString]
(
@Values nvarchar(max),
@ValueSeparator nvarchar(5)
)
RETURNS @Result TABLE
(
Ord int,
Value nvarchar(100) -- can be adjusted
)
AS
BEGIN
;with ValuesToXML as
(
select CAST('<i>' + REPLACE(@Values, @ValueSeparator, '</i><i>') + '</i>' AS XML) as 'Values'
),
ValuesToList as
(
select x.i.value('for $i in . return count(../*[. << $i]) + 1', 'int') as 'Ord',
x.i.value('.', 'NVARCHAR(100)') AS 'Value' -- can be adjusted
from ValuesToXML
CROSS APPLY
[Values].nodes('//i') x(i)
)
INSERT INTO @Result (Ord,Value) select * from ValuesToList;
return;
END
Despite the fact that it is compact, the body is not directly related to understanding. It converts a nvarchar
to a table with XML
.
What's really important about this scored table function
is ... the fact that it can be used as a table in operations SELECT
, of course.
Here are some usage examples.
1) Simple call:
select * from dbo.SplitString('value1;value2;value3;value4', ';')
Result:
Ord Value
1 value1
2 value2
3 value3
4 value4
2) According to your data:
;with records as
(
select * from
(
values (1, '11 999999999 ==> QP' + char(9) + char(13) + '16,9 11,154 ==>SP'),
(2, '99 1049 999999999 ==>QP' + char(9) + char(13) + '2 1,32 0,8 ==>SP')
) as v(id, txt)
),
subrecords1 as
(
select r.id
,s.ord as ord1
,s.value as value
from records r
cross apply
dbo.SplitString(r.txt, char(9) + char(13)) s
),
subrecords2 as
(
select r.id
,r.ord1
,s.ord as ord2
,s.value as value
from subrecords1 r
cross apply
dbo.SplitString(r.value, '==>') s
),
subrecords3 as
(
select r.id
,r.ord1
,r.ord2
,s.ord as ord3
,s.ord3c as ord3c
,s.value as value
from subrecords2 r
cross apply
(
select ord
,row_number() over (order by ord) as ord3c -- consecutive ord3
,ltrim(rtrim(value)) as value
from dbo.SplitString(r.value, ' ')
where value != '' --this will cause ord3 not to be consecutive
)s
)
select * from subrecords3
Result:
id ord1 ord2 ord3 ord3c value
1 1 1 1 1 11
1 1 1 3 2 999999999
1 1 2 2 1 QP
1 2 1 1 1 16,9
1 2 1 5 2 11,154
1 2 2 1 1 SP
2 1 1 1 1 99
2 1 1 3 2 1049
2 1 1 7 3 999999999
2 1 2 1 1 QP
2 2 1 1 1 2
2 2 1 4 2 1,32
2 2 1 8 3 0,8
2 2 2 1 1 SP
Does this mean anything to you?
You can break down the query above and see what each CTE returns.
Here are some tips:
-
id
is the id of the original post - records with
ord1 = 1
andord2 = 2
always'QP'
- records with
ord1 = ord2 = 1
are values ββforQP
- records with
ord1 = ord2 = 2
always'SP'
- records with
ord1 = 2
andord2 = 1
are values ββforSP
Since subrecords3
we have some filtering in the CTE, ord3 will not have consecutive values. For this reason, we are adding a column ord3c
.
subrecords3
Can now be combined with itself on the canvas id, ord1, ord2, ord3c
to display SP values ββwith QP values.
Good luck!
source to share