use*_*552 4 sql t-sql sql-server sql-server-2005
我有一个表,有年,月和几个数字列
Year Month Total
2011 10 100
2011 11 150
2011 12 100
2012 01 50
2012 02 200
Run Code Online (Sandbox Code Playgroud)
现在,我希望SELECT2011年11月至2012年FEB之间的行.请注意,我希望查询使用范围.就好像我在表中有一个日期列一样..
想出一种将BETWEEN与表格一起使用的方法可行,但在每种情况下表现都会更差:
如果您的日期列上有索引并且完全关心性能,我建议您使用以下内容:
DECLARE
@FromDate date = '20111101',
@ToDate date = '20120201';
SELECT *
FROM dbo.YourTable T
WHERE
(
T.[Year] > Year(@FromDate)
OR (
T.[Year] = Year(@FromDate)
AND T.[Month] >= Month(@FromDate)
)
) AND (
T.[Year] < Year(@ToDate)
OR (
T.[Year] = Year(@ToDate)
AND T.[Month] <= Month(@ToDate)
)
);
Run Code Online (Sandbox Code Playgroud)
但是,你可以理解你不想使用这样的结构,因为它非常笨拙.所以这是一个折衷查询,它至少使用数值计算,并且将使用比日期到字符串转换计算更少的CPU(尽管不足以弥补强制扫描,这是真正的性能问题).
SELECT *
FROM dbo.YourTable T
WHERE
T.[Year] * 100 + T.[Month] BETWEEN 201111 AND 201202;
Run Code Online (Sandbox Code Playgroud)
如果你有一个索引Year,你可以通过如下提交查询来获得巨大的推动,这有机会寻求:
SELECT *
FROM dbo.YourTable T
WHERE
T.[Year] * 100 + T.[Month] BETWEEN 201111 AND 201202
AND T.[Year] BETWEEN 2011 AND 2012; -- allows use of an index on [Year]
Run Code Online (Sandbox Code Playgroud)
虽然这打破了使用单个BETWEEN表达式的要求,但它并没有太多的痛苦,并且与Year索引的表现非常好.
您也可以更改您的表格.坦率地说,为日期部分使用单独的数字而不是使用日期数据类型的单个列并不好.它不好的原因是因为你现在面临的确切问题 - 很难查询.
在一些保存字节非常重要的数据仓库场景中,我可以设想您可以将日期存储为数字(例如201111),但不建议这样做.将最好的解决办法是改变你的表使用的日期,而不是分裂出来的月份和年份的数值.只需存储该月的第一天,即可确认它代表整个月份.
如果更改使用这些列的方式不是一个选项,但您仍然可以更改表,那么您可以添加一个持久计算列:
ALTER Table dbo.YourTable
ADD ActualDate AS (DateAdd(year, [Year] - 1900, DateAdd(month, [Month], '18991201')))
PERSISTED;
Run Code Online (Sandbox Code Playgroud)
有了这个,你可以这样做:
SELECT *
FROM dbo.YourTable
WHERE
ActualDate BETWEEN '20111101' AND '20120201';
Run Code Online (Sandbox Code Playgroud)
该PERSISTED关键字意味着,当你仍然会得到一个扫描,它不会做每一行任何计算,因为表达式计算每个INSERT或UPDATE和存储排.但是,你可以得到,如果你在此列,这将使其表现非常好(虽然这一切的一切,这仍然不是理想的,因为改变使用的实际日期列中添加索引查找,因为这将需要更大的空间,会影响INSERT和UPDATE):
CREATE NONCLUSTERED INDEX IX_YourTable_ActualDate ON dbo.YourTable (ActualDate);
Run Code Online (Sandbox Code Playgroud)
总结:如果你真的无法以任何方式改变表格,那么你将不得不以某种方式做出妥协.当您的日期存储拆分为单独的列时,将无法获得您想要的简单语法.
| 归档时间: |
|
| 查看次数: |
1809 次 |
| 最近记录: |