Hi Rudy,
this is pure Standard SQL92, so at least POSITION and SUBSTRING are supported and even Oracle now knows CASE ;-)
But the posted SQL doesn't allow delimiter lists, this is only possible with SQL:1999, i forgot to copy this one:
SELECT
groupcol
,SUBSTRING(string
FROM n
FOR (COALESCE(MAX

OVER (PARTITION BY groupcol
ORDER BY n ROWS BETWEEN 1 FOLLOWING and 1 FOLLOWING)
, 64000)
) - n - 1
) AS word
,ROW_NUMBER() OVER (PARTITION BY groupcol ORDER BY n) AS pos
FROM Strings s, (SELECT n FROM nums WHERE n BETWEEN 1 AND 247) tmp
WHERE
(n <= CHAR_LENGTH(string) AND SUBSTRING(string FROM n - 1 FOR 1) = ',')
OR
n = 1;
Currently Teradata, Oracle and DB2 support those OLAP funuctions.
I'll post a test case from a private MCT trainer forum by Itzik Ben-Gan for MS SQL:
CREATE TABLE Strings
(
groupcol INT NOT NULL,
string VARCHAR(1000) NOT NULL
)
INSERT INTO Strings VALUES(1, 'a')
INSERT INTO Strings VALUES(2, 'b,c')
INSERT INTO Strings VALUES(3, 'd,e,f')
INSERT INTO Strings VALUES(4, 'g,h,i,g')
-- Permanent Auxiliary table - Nums
CREATE TABLE Nums
(
n INT NOT NULL PRIMARY KEY
)
SET NOCOUNT ON
DECLARE
@rc AS INT,
@max AS INT
SET @rc = 1
SET @max = 8000
INSERT INTO Nums VALUES(1)
WHILE @rc * 2 < @max
BEGIN
INSERT INTO Nums
SELECT n + @rc
FROM Nums
SET @rc = @rc + @@rowcount
END
INSERT INTO Nums
SELECT n + @rc
FROM Nums
WHERE n + @rc <= @max
--Itzik's solution
SELECT
groupcol,
SUBSTRING(string, n, CHARINDEX(',', string + ',', n) - n) AS word
FROM Strings JOIN Nums
ON n <= LEN(string) AND SUBSTRING(',' + string, n, 1) = ','
--mine had a longer source code, but was a bit faster ;-)
select
groupcol,
substring(string, n, case when (charindex(',', string, n)) = 0
then 8000
else (charindex(',', string, n))
end - n) as word
from Strings s, nums
where
n <= Len(string)
and
( n = 1
or
substring(string, n - 1, 1) = ','
)
order by groupcol, n
If you have access to the SQLmag archives, that's Itzik's article:
btw, i still don't have a web site...
Dieter