tsql最有效的方法来比较where子句中的三个日期值?

时间:2016-12-07 13:08:07

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

我正在尝试创建一个存储过程。 在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,我选择"更大"日期。 然后我比较这个"更大"日期到日期3。 如果comparsion为true,我会将值写入table。

-- 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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

您可以使用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为null,则对D1检查D2将始终返回false。如果Date1也允许NULL,则此技术将失败。在这种情况下,您可以扩展case表达式以包含更多表达式,或包含ISNULL函数。

第二个选项是sytactic sugar的示例。在幕后,根据MSDN

,SQL Server会将您的代码转换为简单的大小写表达式
  

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

答案 2 :(得分:0)

这是我的建议:

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