Adding a ROW_NUMBER() with no column to ORDER BY?
The canonical way to do this is the following: ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
. If you're golfing, you might try something like this:
SELECT value, n = ROW_NUMBER() OVER(ORDER BY (SELECT 1))
FROM STRING_SPLIT('one,two,three,four,five',',')
It works for the simple case you posted in the question:
I should say that there is not a documented guarantee that the ROW_NUMBER()
value will be in the precise order that you expect. But it's code golf, so this seems good enough.
You can't rely on your INSERT
to generate IDENTITY
values in the order of your original string. That may be what you observe, but that is just lucky coincidence and certainly not guaranteed.
The following will work if you don't have duplicates:
DECLARE @str varchar(255) = 'one,two,three,four,five';
SELECT value, n = ROW_NUMBER() OVER
(ORDER BY CHARINDEX(',' + value + ',', ',' + @str + ','))
FROM STRING_SPLIT('one,two,three,four,five', ',')
ORDER BY n;
For code golf maybe:
DECLARE @s char(99)='one,two,three,four,five';
SELECT value,n=RANK() OVER(ORDER BY CHARINDEX(','+value+',',','+@s+','))
FROM STRING_SPLIT('one,two,three,four,five', ',')ORDER BY n
If you have duplicates it becomes a lot more complex. Some ideas here maybe:
- Removing Duplicates from Strings in SQL Server
- Solve old problems with SQL Server’s new STRING_AGG and STRING_SPLIT functions
Another option is to use a sequence:
DROP SEQUENCE IF EXISTS dbo.S;
CREATE SEQUENCE dbo.S START WITH 1;
SELECT value, NEXT VALUE FOR dbo.S
FROM STRING_SPLIT('one,two,three,four,five', ',');
Output:
╔═══════╦═══╗
║ one ║ 1 ║
║ two ║ 2 ║
║ three ║ 3 ║
║ four ║ 4 ║
║ five ║ 5 ║
╚═══════╩═══╝
It is annoying that STRING_SPLIT
was implemented without a built-in numbering option. Vote for change at https://feedback.azure.com/forums/908035-sql-server/suggestions/32902852-string-split-is-not-feature-complete