Menghasilkan urutan mengubah perilaku pada nomor baris tertentu

pemrograman


Mengalami momen padat/senior hari ini…

Saya memiliki kueri SQL (yang diwarisi) yang dijalankan terhadap cte yang sekarang menghasilkan baris bernomor dari 1 hingga 16384. Saya mengharapkannya menghasilkan huruf kolom dalam rentang “A” hingga “XFC” (Sebelumnya menghasilkan “A” hingga “ZZ “)

Ini seharusnya berhasil

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;

Faktanya, itu melakukan bekerja – SAMPAI kita sampai ke baris 6787 – alih-alih mengembalikan “JAA” melainkan kembali ke “IAA” (sampai ke “IAZ” dan dari sana melakukan beberapa hal aneh dan menakjubkan (termasuk karakter non-ascii))

Saya bisa menyiasatinya dengan

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;

Yang berfungsi hingga “XFC”.

Yang saya tidak mengerti adalah…mengapa?

Saya kesulitan memahami pentingnya 6786 sebagai angka kunci – meskipun saya merasa berlebihan ketika menyadari bahwa itu adalah 26 x 255 tetapi l apakah bigint jadi tidak relevan?

Apa yang saya coba:

Kode lengkap untuk mereproduksi perilaku

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;

Solusi 1

Karena perhitunganmu salah! 😀

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をコピーしました