use*_*935 9 sql sql-server sql-server-2005
快速版:以下是最好的,为什么?(或者,还有更好的方法):
SELECT FLOOR(LOG10(Number))+1 AS NumLength FROM Table
SELECT LEN(CONVERT(VARCHAR, Number)) AS NumLength FROM Table
SELECT LEN(CAST(Number AS VARCHAR(10))) AS NumLength FROM Table
Run Code Online (Sandbox Code Playgroud)
更详细一点:
我希望找出最有效的机制来计算整数的字符串表示的长度(更具体地说,是一个自然数 - 总是> 0).
我正在使用MS SQL Server(2005).
我已经提出了上面的3种解决方案,所有这些解决方案似乎都运行良好.
我知道第三个版本可能存在非常大的整数问题,但是现在我们可以假设"数字"长度不超过9位十进制数.
更详细的说明:( 你不必阅读这一点来回答我的问题)
这个查询在事务处理环境中被大量使用.
到目前为止,我已经假设"数字"总是正好是6位数.
但是,现在我必须更新代码以支持4到9位数字.
此SQL是识别卡的卡方案的条件的一部分.
完整查询尝试在开始和结束范围内查找与卡号开头匹配的记录.
所以完整的SQL条件将是这样的:
WHERE
-- Start and End match
((Start=End OR End=0) AND (Start=CAST(LEFT('<card number>', FLOOR(LOG10(Start))+1) AS BIGINT))) OR
-- Start != End
-- >= Start
(Start<=CAST(LEFT('<card number>', FLOOR(LOG10(Start))+1) AS BIGINT) AND
-- <= End
End>=CAST(LEFT('<card number>', FLOOR(LOG10(Start))+1) AS BIGINT))
Run Code Online (Sandbox Code Playgroud)
注意:
我可以重新设计表以使用VARCHAR而不是INT.这将允许我使用"LEN(开始)"而不是"FLOOR(LOG10(开始))+ 1)"但是条件将具有更多的CAST.
我更愿意继续处理INT,因为数据库模式将保持不变,并且无论如何处理INT应该比VARCHAR更快.
如果我将字段更改为VARCHAR,我的条件可能是:
WHERE
-- Start and End match
((Start=End OR LEN(End)=0) AND (Start=LEFT('<card number>', LEN(Start)))) OR
-- Start != End
-- >= Start
(CAST(Start AS BIGINT)<=CAST(LEFT('<card number>', LEN(Start)) AS BIGINT) AND
-- <= End
CAST(End AS BIGINT)>=CAST(LEFT('<card number>', LEN(Start)) AS BIGINT))
Run Code Online (Sandbox Code Playgroud)
非常感谢任何帮助,
戴夫
在我的机器上,版本 2 和版本 3 的结果大致相同,并且击败了其他两个。
编辑:虽然我刚刚想到我最初的测试有点不公平,CASE因为按升序排列语句意味着只有 10 个可能的数字满足第一个条件并提前退出。我在下面添加了一个额外的测试。您也可以尝试嵌套CASE语句来进行二分搜索。
SET NOCOUNT ON
SET STATISTICS TIME ON
PRINT 'Test 1';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(FLOOR(LOG10(N))+1)
FROM cteTally
WHERE N <= 10000000;
PRINT 'Test 2';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(LEN(CONVERT(VARCHAR, N)))
FROM cteTally
WHERE N <= 10000000;
PRINT 'Test 3';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(LEN(CAST(N AS VARCHAR(10))))
FROM cteTally
WHERE N <= 10000000;
PRINT 'Test 4';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(CASE
WHEN N < 10 THEN 1
WHEN N < 100 THEN 2
WHEN N < 1000 THEN 3
WHEN N < 10000 THEN 4
WHEN N < 100000 THEN 5
WHEN N < 1000000 THEN 6
WHEN N < 10000000 THEN 7
WHEN N < 100000000 THEN 8
END)
FROM cteTally
WHERE N <= 10000000;
PRINT 'Test 5';
WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
E02(N) AS (SELECT 1 FROM E00 a, E00 b),
E04(N) AS (SELECT 1 FROM E02 a, E02 b),
E08(N) AS (SELECT 1 FROM E04 a, E04 b),
E16(N) AS (SELECT 1 FROM E08 a, E08 b),
E32(N) AS (SELECT 1 FROM E16 a, E16 b),
cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
SELECT MAX(CASE
WHEN N >= 100000000 THEN NULL
WHEN N >= 10000000 THEN 8
WHEN N >= 1000000 THEN 7
WHEN N >= 100000 THEN 6
WHEN N >= 10000 THEN 5
WHEN N >= 1000 THEN 4
WHEN N >= 100 THEN 3
WHEN N >= 10 THEN 2
ELSE 1
END )
FROM cteTally
WHERE N <= 10000000;
Run Code Online (Sandbox Code Playgroud)
在我的机器上运行的示例的结果是
Test 1
CPU time = 9422 ms, elapsed time = 9523 ms.
Test 2
CPU time = 7021 ms, elapsed time = 7130 ms.
Test 3
CPU time = 6864 ms, elapsed time = 7006 ms.
Test 4
CPU time = 9328 ms, elapsed time = 9456 ms.
Test 5
CPU time = 6989 ms, elapsed time = 7358 ms.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
36898 次 |
| 最近记录: |