Thêm ROW_NUMBER () không có cột để ĐẶT HÀNG B? NG?


7

Vì vậy, tôi đang làm việc trên một câu đố golf đang và cần phải thêm một INT "number" cột n đến kết quả trong một thời gian duy trì trật tự hiện hành.

Giả sử dữ liệu nguồn của tôi là:

SELECT value
FROM STRING_SPLIT('one,two,three,four,five', ',')

trong đó trả về các mục theo thứ tự ban đầu (mong muốn):

value
-----
one
two
three
four
five

Nếu tôi cố gắng sử dụng ROW_NUMBER()hoặc RANK()tôi buộc phải chỉ định một ORDER BY, đó valuelà lựa chọn hợp pháp duy nhất:

SELECT value, n = ROW_NUMBER() OVER(ORDER BY value)
FROM STRING_SPLIT('one,two,three,four,five',',')

Nhưng điều này (như mong đợi) sắp xếp valuetheo thứ tự abc thay vì để nó theo thứ tự ban đầu mong muốn:

value   n
------ ---
five    1
four    2
one     3
three   4
two     5

Tham gia vào một bảng số không hoạt động, vì không có WHEREđiều khoản, tôi sẽ tham gia bên ngoài đầy đủ.

Về điều tốt nhất tôi có thể nghĩ ra là sử dụng bảng tạm thời với trường nhận dạng:

CREATE TABLE #argg (n INT IDENTITY(1,1), v VARCHAR(99))

INSERT #argg 
SELECT value v
FROM STRING_SPLIT('one,two,three,four,five',',')

SELECT *
FROM #argg

DROP TABLE #argg

nhưng điều này thực sự dài và gây phiền nhiễu. Còn ý tưởng nào hay hơn không?

Câu trả lời:


10

Cách chính tắc để làm điều này là như sau : ROW_NUMBER() OVER(ORDER BY (SELECT NULL)). Nếu bạn đang chơi gôn, bạn có thể thử một cái gì đó như thế này:

SELECT value, n = ROW_NUMBER() OVER(ORDER BY (SELECT 1))
FROM STRING_SPLIT('one,two,three,four,five',',')

Nó hoạt động cho trường hợp đơn giản mà bạn đã đăng trong câu hỏi:

nhập mô tả hình ảnh ở đây

Tôi nên nói rằng không có một đảm bảo nào được ghi nhận rằng ROW_NUMBER()giá trị sẽ theo thứ tự chính xác mà bạn mong đợi. Nhưng đó là mã golf, vì vậy điều này có vẻ đủ tốt.


6

Bạn không thể dựa vào INSERTđể tạo IDENTITYcác giá trị theo thứ tự chuỗi ban đầu của bạn. Đó có thể là những gì bạn quan sát, nhưng đó chỉ là sự trùng hợp may mắn và chắc chắn không được đảm bảo.

Những điều sau đây sẽ hoạt động nếu bạn không có bản sao:

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;

Đối với mã golf có thể:

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

Nếu bạn có các bản sao, nó trở nên phức tạp hơn rất nhiều. Một số ý tưởng ở đây có thể:


Khá thông minh, nhưng vâng, các dups sẽ là một vấn đề. Tôi chưa bao giờ có STRING_SPLITcác phần tử trả về theo thứ tự khác với điều hiển nhiên, nhưng có lẽ với một số chuỗi dài điên rồ thì có thể. Cảm ơn.
BradC

5

Một tùy chọn khác là sử dụng một chuỗi:

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', ',');

Đầu ra:

╔═══════╦═══╗
 one    1 
 two    2 
 three  3 
 four   4 
 five   5 
╚═══════╩═══╝

Thật khó chịu khi STRING_SPLITđược thực hiện mà không có tùy chọn đánh số tích hợp. Bình chọn cho sự thay đổi tại https://feedback.azure.com/forums/908035-sql-server/suggestions/32902852-opes-split-is-not-feature-complete


Whoa, không biết về trình tự, tôi chắc chắn sẽ kiểm tra chúng! Và có, bao gồm cả như là một cột trả lại bổ sung từ STRING_SPLITsẽ là hoàn toàn lý tưởng!
BradC

2

Chỉ cần thêm một thay thế từ câu hỏi của bạn. Nhưng tôi nghĩ việc đặt hàng không được đảm bảo,

SELECT value v,IDENTITY(INT,1,1) AS n
INTO #argg
FROM STRING_SPLIT('one,two,three,four,five',',')

SELECT * FROM #argg

Đó là một mẹo khá hay, không biết bạn có thể sử dụng IDENTITY()theo cách đó! để làm rõ hơn, INTObắt buộc phải thực hiện công việc đó, nếu không bạn sẽ nhận đượcThe IDENTITY function can only be used when the SELECT statement has an INTO clause.
BradC
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.