在此处使用Microsoft SQL Server。 鉴于此设置(两列上的聚簇索引):
use tempdb;
CREATE TABLE mytemp
(
N1 INT NOT NULL,
N2 INT NOT NULL,
PRIMARY KEY (N1, N2)
);
INSERT mytemp (N1, N2)
SELECT N1.number, N2.number
FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS N1(number)
CROSS JOIN (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS N2(number)
如何在n1 = 5,n2 = 6(按n1,n2排序)后得到值?我有以下尝试。
declare @n1boundary int = 5;
declare @n2boundary int = 6;
SELECT N1, N2
FROM mytemp
WHERE N1 = @n1boundary AND N2 > @n2boundary
OR N1 > @n1boundary
ORDER BY N1, N2
它给了我想要的结果,但语法看起来很笨拙,它执行两次扫描。在我看来,从理论上讲,应该可以通过一次扫描来完成这项工作。
[编辑]我正在查看的扫描是在SET STATISTICS IO设置为ON的情况下报告的:
Table 'mytemp'. Scan count 2, logical reads 4
答案 0 :(得分:0)
当我在我的系统上尝试时,我进行了一次搜索操作。
Microsoft SQL Server 2008(SP1) - 10.0.2531.0(X64)2009年3月29日10:11:52版权所有(c)1988-2008 微软公司标准 Windows NT 5.2上的版本(64位) (Build 3790:Service Pack 2) (VM)
答案 1 :(得分:0)
当我运行这个时,我得到了一个相当不错的执行计划,仅执行聚簇索引查找。
另一个选项如下所示,使用复合键,但这会产生聚簇索引SCAN,因此在大型表上性能可能不太好
declare @n1boundary int = 5;
declare @n2boundary int = 6;
select N1, N2
from mytemp
where cast(N1 as varchar(2))+cast((N2-1) as varchar(2)) >
cast(cast(@n1boundary as varchar(2))+cast((@n2boundary-1) as varchar(2)) as int)
答案 2 :(得分:0)
根据PCurd的回答,这是另一个古怪的解决方法。它会持久保存聚簇索引,对其进行索引,然后对其进行简单的范围扫描:
ALTER TABLE mytemp
ADD stringify as
right('00' + cast(n1 as varchar), 2) +
right('00' + cast(n2 as varchar), 2) PERSISTED;
CREATE NONCLUSTERED INDEX ix_mytemp
ON mytemp(stringify)
INCLUDE (n1, n2)
declare @n1boundary int = 5;
declare @n2boundary int = 6;
SELECT n1, n2
FROM mytemp
WHERE stringify >
right('00' + cast(@n1boundary as varchar), 2) +
right('00' + cast(@n2boundary as varchar), 2)
ORDER BY stringify;
它很草率,也不是我想要的。