Tạo hành vi thay đổi trình tự trên số hàng cụ thể

lập trình


Hôm nay có một khoảnh khắc dày đặc/cao cấp…

Tôi có một truy vấn SQL (được kế thừa) chạy trên một cte hiện tạo ra các hàng được đánh số từ 1 đến 16384. Tôi hy vọng nó sẽ tạo các chữ cái cột trong phạm vi từ “A” đến “XFC” (Được tạo trước đó là “A” đến “ZZ “)

Điều này sẽ hoạt động

SQL
SELECT l, CASE WHEN l >= 703 THEN Char(65 + (l - 703) / 702 % 702) ELSE '' END 
			+ CASE WHEN l >=27 then Char(65 + (l - 27) / 26 % 26) ELSE '' END
			+ Char(65 + (l  - 1) % 26)
FROM eFinal
WHERE l < 16384
ORDER BY l;

Trên thực tế, nó làm công việc – ĐẾN KHI chúng ta đến hàng 6787 – thay vì trả về “JAA”, nó sẽ trở lại “IAA” (đến “IAZ” và từ đó thực hiện một số điều kỳ lạ và tuyệt vời (bao gồm cả các ký tự không phải mã ascii))

Tôi có thể giải quyết nó với

SQL
SELECT l, (CASE WHEN l >= 6787 THEN Char((65 + (l - 703) / 702 % 702) + 1) 
				WHEN l >= 703 THEN  Char(65 + (l - 703) / 702 % 702) ELSE '' END)
		+ (CASE WHEN l > 27 THEN (Char(65 + (l - 27) / 26 % 26)) ELSE '' END)
			+(Char(65 + (l  - 1) % 26))
FROM eFinal
WHERE l < 16384
ORDER BY l;

Nó hoạt động hoàn toàn theo cách “XFC”.

Điều tôi không hiểu là… tại sao?

Tôi đang cố gắng hiểu ý nghĩa của 6786 như một con số quan trọng – mặc dù tôi đã quá phấn khích khi nhận ra đó là 26 x 255 nhưng l là một bigint nên không liên quan?

Những gì tôi đã thử:

Mã đầy đủ để tái tạo hành vi

SQL
;with 
 cte1 AS (select n from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1) ) AS X(n))
,cte2 AS (SELECT a.n FROM cte1 a CROSS JOIN cte1 b)	-- 10*10
,cte3 AS (SELECT a.n FROM cte1 a CROSS JOIN cte2 b)	-- 10*100
,cte4 AS (SELECT a.n FROM cte2 a CROSS JOIN cte3 b )	-- 1000*100
,eFinal AS (SELECT l = ROW_NUMBER() OVER (ORDER BY a.n) FROM cte2 a CROSS JOIN cte3 b )
SELECT l, CASE WHEN l >= 703 THEN Char(65 + (l - 703) / 702 % 702) ELSE '' END 
			+ CASE WHEN l >=27 then Char(65 + (l - 27) / 26 % 26) ELSE '' END
			+ Char(65 + (l  - 1) % 26)
FROM eFinal
--WHERE l < 16384
where l BETWEEN 6780 AND 6790
ORDER BY l;

Giải pháp 1

Bởi vì phép toán của bạn sai! 😀

SQL
DECLARE @cnt INT = 6785; 
WHILE @cnt < 6789 
BEGIN 
	SELECT @cnt
	     , (@cnt - 27) / (26 * 26)
		 , CASE WHEN (@cnt - 27 / (26 * 26)) > 0 THEN CHAR(65 + ((@cnt - 27) / (26 * 26))) ELSE '' END
		 , Char(65 + (@cnt - 27) / 26 % 26)
		 , Char(65 + (@cnt  - 1) % 26)
	SET @cnt = @cnt + 1;
END

コメント

タイトルとURLをコピーしました