【问题标题】:How do I avoid the use of getdate() in a SQL view?如何避免在 SQL 视图中使用 getdate()?
【发布时间】:2010-10-29 17:55:21
【问题描述】:

我正在编写一个数据库视图来总结一堆记录,其中日期列中的值在过去 7 天内。它看起来像这样:

CREATE VIEW RecentRecordSum AS
SELECT      t.ID,   
            SUM(t.SomeValue) AS ValueSum
FROM        SomeTable t
WHERE       t.RecordDate >= DATEADD(d,-7,GETDATE())
GROUP BY    t.ID

有没有办法在 where 子句中不直接使用 GETDATE() ?

我使用的是 SQL Server 2000 和 2005。

查看查询计划表明 getdate() 调用的成本仅为整个查询的 0.03%(这比上面的要复杂得多),因此性能不是问题,但是我喜欢我的查询是确定性的。

理想情况下,我还希望将 -7 参数公开为一列,以便可以在查询视图的 where 子句中使用它。目前,我正在考虑 7、14、28 天窗口的少量观看次数。

【问题讨论】:

  • 不确定我是否理解这个问题。如果不在 where 子句中,它会在哪里?您是否在考虑传入的某种参数?
  • 我假设这是为了避免为结果集的每一行评估 GETDATE() 对性能造成影响。
  • 你为什么假设它是针对每一行进行评估的?
  • 我不知道,但我不认为行为被定义为任何一种方式。
  • 实际上是 DATEADD(d,-7,GETDATE()),确实是性能问题,与其说是被评估,不如说是因为它使得在 RecordDate 上使用索引不太可能,因为它是与表达式的比较。

标签: sql sql-server database view


【解决方案1】:

您提出问题的一个原因可能是通过删除数据转换使视图更加优化。不能在视图中执行此操作,您需要将其设为存储过程并将其转换为变量:

CREATE PROCEDURE RecentRecordSum AS

DECLARE @adate DATETIME

SELECT @adate = DATEADD(d, -7, GETDATE())

SELECT      t.ID,   
            SUM(t.SomeValue) AS ValueSum  
FROM        SomeTable t  
WHERE       t.RecordDate >= @adate  
GROUP BY    t.ID  

【讨论】:

    【解决方案2】:

    和其他人一样,在黑暗中再次开枪......

    也许您希望将其设为索引视图,而 getdate() 无法做到这一点,因为它是一个不确定的函数。我过去曾通过从另一个仅包含的视图中调用 getdate() 来规避这一点

    select getdate()
    

    这种间接级别足以欺骗 SQL Server 2000 并允许我使用架构绑定,但我不能保证这将适用于以后的版本。

    【讨论】:

    • 在 2008 年尝试过。不幸的是,没有成功 Msg 4513, Level 16, State 2, Procedure view_ProductSearch, Line 5 [Batch Start Line 9] Cannot schema bind view 'dbo.view_ProductSearch'. 'dbo.view_CurrentDate' is not schema bound.
    • 我不建议这样做,但您可以创建一个返回当前日期并将其标记为 IsDeterministic 的 CLR 函数。
    【解决方案3】:

    如果我对问题的理解正确,您总是可以尝试使用包含 GETDATE() 的集合进行内部连接,如下面的查询:

    SELECT      t.ID,   
                SUM(t.SomeValue) AS ValueSum
    FROM        SomeTable t
    INNER JOIN (SELECT DATEADD(d,-7,GETDATE()) AS MIN_DATE) MIN_DATE_SET
    ON t.RecordDate >= MIN_DATE_SET.MIN_DATE
    GROUP BY    t.ID
    

    编辑: 我查看了类似场景的查询计划,它们是相同的。 YMMV。

    【讨论】:

      【解决方案4】:
      SELECT CURRENT_TIMESTAMP
      
      SELECT {fn NOW()}
      

      我可能误解了这个问题,如果您只是想移动 GetDate() 而不是替换它,您可以在 Have 子句中进行评估,即

      CREATE VIEW RecentRecordSum AS
      SELECT      t.ID,   
                  SUM(t.SomeValue) AS ValueSum
      FROM        SomeTable t
      GROUP BY    t.ID, t.RecordDate
      HAVING      t.RecordDate >= DATEADD(d,-7,GETDATE())
      

      【讨论】:

        【解决方案5】:

        假设您有最近一天的数据,子查询可能会起作用:

        CREATE VIEW RecentRecordSum AS
        SELECT      t.ID,   
                    SUM(t.SomeValue) AS ValueSum
        FROM        SomeTable t
        WHERE       t.RecordDate >= DATEADD(d,-7,(Select Max(RecordDate) From SomeTable))
        GROUP BY    t.ID
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-02
          • 1970-01-01
          • 2010-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多