That's my table
123 | 123-456-345
234 | 332-433
221 | 221
That's the result that I want to get
123 | 123
123 | 456
123 | 345
234 | 332
234 | 433
221 | 221
That's my table
123 | 123-456-345
234 | 332-433
221 | 221
That's the result that I want to get
123 | 123
123 | 456
123 | 345
234 | 332
234 | 433
221 | 221
With SQL-Server you could do this:
DECLARE @tbl TABLE(ID INT,YourString VARCHAR(MAX));
INSERT INTO @tbl VALUES(123,'123-456-345'),(234,'332-433'),(221,'221');
SELECT tbl.ID
,x.value('.','int') AS Value
FROM @tbl AS tbl
CROSS APPLY(SELECT CAST('<x>' + REPLACE(YourString,'-','</x><x>') + '</x>' AS XML)) AS Casted(AsXml)
CROSS APPLY Casted.AsXml.nodes('/x') AS A(x)
The trick is, to transform your string 123-456-345
to valid XML with simple replacements of -
: <x>123</x><x>456</x><x>345</x>
.
This XML can be queried using .nodes()
, to get all entries one after the other
If you are using SQL Server 2016 , use STRING_SPLIT function.
SELECT ID, value
FROM Yourtable
CROSS APPLY STRING_SPLIT([YourColumn], '-');
For lower versions of SQL server,you can either follow what @shungo suggested,or you can create a user defined function to split string and call it in the select statement.
CREATE FUNCTION [dbo].[SplitWords]
(
@Input NVARCHAR(MAX),
@Character CHAR(1)
)
RETURNS @Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
DECLARE @StartIndex INT, @EndIndex INT
SET @StartIndex = 1
IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
BEGIN
SET @Input = @Input + @Character
END
WHILE CHARINDEX(@Character, @Input) > 0
BEGIN
SET @EndIndex = CHARINDEX(@Character, @Input)
INSERT INTO @Output(Item)
SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)
SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
END
RETURN
END
The write the script like below.
SELECT ID,Item
FROM Yourtable
CROSS APPLY [SplitWords] (YourColumn,'-')
If you are using Postgres you can use string_to_array()
and unnest()
:
select t.id, x.val
from the_table t
cross join lateral unnest(string_to_array(the_column), '-') as x(val);
But you should really fix your data model. Storing delimited strings in a single column is a really bad idea.
For the Oracle 11g here is a simple solution (Just replace tab
with your-table-name and num
, str
with your-column-names):
WITH
tab1 AS (
SELECT num, SUBSTR(str,1,3) str FROM tab
UNION ALL
SELECT num, SUBSTR(str,5,3) str FROM tab
UNION ALL
SELECT num, SUBSTR(str,9,3) str FROM tab
)
SELECT *
FROM tab1
WHERE str IS NOT NULL
It gives me result of:
1 123 123
2 123 345
3 123 456
4 221 221
5 234 332
6 234 433