Tsql 在T-SQL中使用DATEDIFF

Tsql 在T-SQL中使用DATEDIFF,tsql,datediff,Tsql,Datediff,我正在SQL语句中使用DATEDIFF。我正在选择它,我还需要在WHERE子句中使用它。这个声明不起作用 SELECT DATEDIFF(ss, BegTime, EndTime) AS InitialSave FROM MyTable WHERE InitialSave <= 10 它给出消息:无效的列名InitialSave 但这句话很好用 SELECT DATEDIFF(ss, BegTime, EndTime) AS InitialSave FROM MyTable WHERE

我正在SQL语句中使用DATEDIFF。我正在选择它,我还需要在WHERE子句中使用它。这个声明不起作用

SELECT DATEDIFF(ss, BegTime, EndTime) AS InitialSave
FROM MyTable
WHERE InitialSave <= 10
它给出消息:无效的列名InitialSave

但这句话很好用

SELECT DATEDIFF(ss, BegTime, EndTime) AS InitialSave
FROM MyTable
WHERE DATEDIFF(ss, BegTime, EndTime) <= 10
我的程序员说这是低效的,好像我调用了两次函数


所以有两个问题。为什么第一个语句不起作用?使用第二条语句是否效率低下?

您必须使用函数而不是列别名-与count*等PITA相同。

作为替代,您可以使用。

您不能访问where语句中select语句中定义的列,因为它们是在where执行之后才生成的

但是你可以这样做

select InitialSave from 
(SELECT DATEDIFF(ss, BegTime, EndTime) AS InitialSave
FROM MyTable) aTable
WHERE InitialSave <= 10
作为旁注,这实际上是将DATEDIFF移动到where语句中,以确定它的第一个定义位置。在where语句中的列上使用函数会导致索引的使用效率降低,如果可能的话应该避免使用,但是如果必须使用datediff,那么就必须这样做

注意:当我最初写这个答案时,我说其中一列上的索引可以创建一个比其他答案性能更好的查询,并提到了Dan Fuller的。然而,我的想法并不是100%正确。事实是,如果没有计算列或索引物化视图,则需要进行完整的表扫描,因为要比较的两个日期列来自同一个表

我相信下面的信息仍然有价值,即1在正确的情况下提高性能的可能性,如在不同表的列之间进行比较,2在SQL开发人员中培养遵循最佳实践并以正确的方向重塑思维的习惯

创造条件

我所指的最佳实践是将一列移动到比较运算符的一侧,如下所示:

SELECT InitialSave = DateDiff(second, T.BegTime, T.EndTime)
FROM dbo.MyTable T
WHERE T.EndTime <= T.BegTime + '00:00:10'
现在,在地板操作中,最大舍入误差仅为1秒,实际上不是两秒。请注意,您只能减去datetime数据类型,以减去必须转换为datetime的日期或时间值,或者使用其他方法来获得更高的精度—大量DateAdd、DateDiff和其他垃圾,或者可能使用更高精度的时间单位和除法

这一原则在计算较大的单位(如小时、天或月)时尤为重要。一个月的DateDiff可能相隔62天,想想2013年7月1日到2013年8月31日吧

除了让它工作之外,还需要使用索引

使用带索引的计算列或带索引的视图,否则将进行表扫描。当你得到足够的行数时,你会感觉到慢扫描的痛苦

计算列和索引:

ALTER TABLE MyTable ADD
    ComputedDate  AS DATEDIFF(ss,BegTime, EndTime)
GO
CREATE NONCLUSTERED INDEX IX_MyTable_ComputedDate  ON MyTable 
    (
    ComputedDate
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
创建视图和索引:

CREATE VIEW YourNewView
AS
SELECT
    KeyValues
        ,DATEDIFF(ss, BegTime, EndTime) AS InitialSave
    FROM MyTable
GO
CREATE CLUSTERED INDEX IX_YourNewView
    ON YourNewView(InitialSave)
GO

不进行多次相同的大量计算是否足够聪明?我很怀疑。所以,如果我选择20列,除了这个,我将需要在内部和外部语句中选择它们,对吗?有更好的方法吗?如果你想的话,你可以在第一行使用select*,而不是选择InitialSave、Col2、Col3等等。哦,糟了!谢谢在视图上创建索引并不总是灵丹妙药。我认为您会发现EndTime列上的索引将执行得足够好,并且不会有更新开销。这确实可以归结为更新/选择模式。这是一个非常好的观点,使用计算列实际上取决于数据和使用列的频率。如果该列所用于的表可能如中所示大,则有数百万行+且所讨论的列为:1。将在应用程序2的一般运行中非常频繁地使用。需要快速访问的执行级员工很少访问。然后应使用计算列。否则最好不要使用它,也不要减慢插入/更新的速度。这太傻了。当我发表这一评论时,我并没有装出一副傲慢的样子,而是试图对那些可能不知道我所描述的事情的实际效果的人提供真正的帮助。请重读我写的:我是不是太精确了一点,但实际上并没有侮辱人?哦。。。和-1由于您误解了一个单词,所以我的查询性能更好。。。在这里填空,但不是免费的。嘿,老兄,我想分享我能分享的。
ALTER TABLE MyTable ADD
    ComputedDate  AS DATEDIFF(ss,BegTime, EndTime)
GO
CREATE NONCLUSTERED INDEX IX_MyTable_ComputedDate  ON MyTable 
    (
    ComputedDate
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE VIEW YourNewView
AS
SELECT
    KeyValues
        ,DATEDIFF(ss, BegTime, EndTime) AS InitialSave
    FROM MyTable
GO
CREATE CLUSTERED INDEX IX_YourNewView
    ON YourNewView(InitialSave)
GO