【问题标题】:tsql most effective way to compare three date values in where clause?sql最有效的方法来比较where子句中的三个日期值?
【发布时间】:2017-04-22 10:47:39
【问题描述】:

我正在尝试创建一个存储过程。 在 where 子句中比较三个日期值的最有效方法是什么?

例子:

tbl1.Date1, 
tbl2.Date2, -- NOTE: Date2 can be NULL.
tbl3.Date3

示例数据:

Date1           Date2           Date3
2016-12-20      2016-11-21      2016-11-30
2016-11-21      NULL            2016-12-20

首先,我比较 Date1 和 Date2,然后选择“更大”的日期。 然后我将这个“更大”的日期与 Date3 进行比较。 如果比较为真,我将值写入表。

-- This is simplified example:
INSERT INTO records
(
    [user_date],
    [user_name]
)
SELECT 
    tbl1.Date1, 
    tbl1.user_name
FROM 
    table1 AS tbl1
    INNER JOIN table2 AS tbl2 ON tbl1.id = tbl2.id
    INNER JOIN table3 AS tbl3 ON tbl2.id = tbl3.id
WHERE
    -- I need to know what is bigger, Date1 or Date2, so I can compare correct date to Date3.
    ISNULL(tbl2.Date2, tbl1.Date1) <= tbl3.Date3 -- ISNULL, doesn't work here, because Date2 and Date1 can get a value and comparison fails if Date1 is bigger than Date3.
    AND ISNULL(tbl2.Date2, tbl1.Date1) > tbl3.last_date

【问题讨论】:

    标签: sql sql-server performance tsql stored-procedures


    【解决方案1】:

    也许是这样的?

    Declare @tbl1 table (id int,date1 date);Insert Into @tbl1 values (1,'2016-12-20'),(2,'2016-11-21 ');
    Declare @tbl2 table (id int,date2 date);Insert Into @tbl2 values (1,'2016-11-21'),(2,null);
    Declare @tbl3 table (id int,date3 date);Insert Into @tbl3 values (1,'2016-12-30'),(2,'2016-12-20');
    
    
    Select User_Date = (Select max(d) from (values(date1),(date2),(date3)) D(D))
          ,A.ID
     From  @tbl1 A
     Join  @tbl2 B on A.ID=B.ID
     Join  @tbl3 C on A.ID=C.ID
    

    返回

    User_Date   ID
    2016-12-30  1
    2016-12-20  2
    

    【讨论】:

      【解决方案2】:

      您可以使用case expressioninline if 有条件地返回两个日期中较大的一个,以进行比较。

      样本数据

      -- Sample data.
      DECLARE @Sample TABLE
          (
              Date1   DATE    NOT NULL,
              Date2   DATE    NULL,
              Date3   DATE    NOT NULL
          )
      ;
      
      INSERT INTO @Sample
          (
              Date1,
              Date2,
              Date3
          )
      VALUES
          ('2016-01-02', NULL,            '2016-01-01'),  -- D1 > D3.
          ('2015-12-31', '2016-01-02',    '2016-01-01'),  -- D2 > D1 and D3
          ('2015-12-30', '2016-12-31',    '2016-01-01')   -- D3 > D1 and D2
      ;
      

      案例表达

      -- Using a CASE EXPRESSION.
      SELECT
          CASE WHEN s.Date2 > s.Date1 THEN s.Date2 ELSE s.Date1 END AS Bigger_of_D1_D2,
          *
      FROM
          @Sample AS s                        
      WHERE
          CASE WHEN s.Date2 > s.Date1 THEN s.Date2 ELSE s.Date1 END > s.Date3
      ;
      

      内联 If(SQL Serer 2012 或更高版本)

      -- Using an INLINE IF.
      SELECT
          IIF(s.Date2 > s.Date1, s.Date2, s.Date1) AS Bigger_of_D1_D2,
          *
      FROM
          @Sample AS s                        
      WHERE
          IIF(s.Date2 > s.Date1, s.Date2, s.Date1) > s.Date3
      ;       
      

      这两种方法都依赖于 NULL 不等于任何东西的事实,包括自身。这意味着如果 Date2 为空,则根据 D1 检查 D2 将始终返回 false。如果 Date1 也允许 NULL,则此技术将失败。在这种情况下,您可以扩展 case 表达式以包含更多 where 表达式,或包含 ISNULL 函数。

      第二个选项是sytactic sugar 的示例。在幕后,SQL Server 会将您的代码转换为简单的 case 表达式,如 MSDN

      IIF 是编写 CASE 表达式的简写方式。

      【讨论】:

      • 就我而言,IIF 是最好的解决方案 =) 谢谢!
      【解决方案3】:

      这是我的建议:

      INSERT INTO records
      (
          [user_date],
          [user_name]
      )
      SELECT tbl1.Date1 
            ,tbl1.user_name
      FROM  table1 as tbl1
      INNER JOIN  table2 as tbl2 on tbl1.ID=tbl2.ID
      INNER JOIN  table3 as tbl3 on tbl1.ID=tbl3.ID
      WHERE (SELECT CASE WHEN tbl1.Date1 > ISNULL(tbl2.Date2,'1900-01-01') THEN tbl1.Date1 ELSE tbl2.Date2 END) <= tbl3.Date3
            AND 
            (SELECT CASE WHEN tbl1.Date1 > ISNULL(tbl2.Date2,'1900-01-01') THEN tbl1.Date1 ELSE tbl2.Date2 END) > tbl3.last_date
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-16
        • 2021-10-09
        • 1970-01-01
        • 2012-01-02
        • 2012-11-10
        • 2022-11-15
        相关资源
        最近更新 更多