如何使SQL查询中的重复自定义表达式可维护

时间:2019-03-05 00:16:36

标签: sql sql-server tsql

想象一下下面的简单查询,我会得到最近三天内创建的所有用户的列表,逻辑或示例并不重要

SELECT
    ...
    , DATEDIFF(DAY, U.DateCreated, GETUTCDATE())
    ...
FROM
    dbo.AspNetUsers U
WHERE
    DATEDIFF(DAY, U.DateCreated, GETUTCDATE()) < 3

我重复了一些代码DATEDIFF(DAY, U.DateCreated, GETUTCDATE()) < 3,当我有上述复杂得多的示例时,我不想维护两次或多次维护该逻辑。

人们应该如何着眼于性能来进行处理?

谢谢

4 个答案:

答案 0 :(得分:3)

如果您考虑到性能,那么最好在需要时重复表达式。 具体来说,不要尝试将它们放在用户定义的函数中。众所周知,它们会使SQL Server中的查询变慢。

话虽如此,SQL Server中至少有两种方法可以使查询更具可读性而不影响性能:

  1. CTE
  2. 交叉申请

使用CTE的示例:

WITH
CTE
AS
(

    SELECT
        ...
        , DATEDIFF(DAY, U.DateCreated, GETUTCDATE()) AS CalculatedColumn
        ...
    FROM
        dbo.AspNetUsers U

)
SELECT
    ...
    CalculatedColumn
    ...
FROM CTE
WHERE
    CalculatedColumn < 3
;

使用CROSS APPLY的示例:

而不是在以下查询中重复部分公式:

SELECT
    ColA + ColB AS ColSum
    ,ColA - ColB AS ColDiff
    ,(ColA + ColB) * (ColA - ColB) AS Result
    ,(ColA + ColB) * (ColA - ColB) * 100.0 AS Percentage
FROM Table

您可以使用CROSS APPLY这样写:

SELECT
    ColSum
    ,ColDiff
    ,Result
    ,Result * 100.0 AS Percentage
FROM
    Table
    CROSS APPLY
    (
        SELECT
            ColA + ColB AS ColSum
            ,ColA - ColB AS ColDiff
    ) AS A1
    CROSS APPLY
    (
        SELECT ColSum * ColDiff AS Result
    ) AS A2

顺便说一句,关于性能,

WHERE DATEDIFF(DAY, U.DateCreated, GETUTCDATE()) < 3

很糟糕,因为它不能在DateCreated上使用索引(因为您将列包装在函数中)。

您最好将其重写为类似的内容

WHERE U.DateCreated > DATEADD(DAY, -3, GETUTCDATE())

答案 1 :(得分:3)

我将CROSS APPLYVALUES一起使用:

SELECT . . ., v.diff
FROM dbo.AspNetUsers U CROSS APPLY
     (VALUES (DATEDIFF(DAY, U.DateCreated, GETUTCDATE()))
     ) v(diff)
WHERE v.diff < 3;

您可以将多个表达式添加到values子句:

SELECT . . ., v.diff
FROM dbo.AspNetUsers U CROSS APPLY
     (VALUES (DATEDIFF(DAY, U.DateCreated, GETUTCDATE()),
              YEAR(U.DateCreated)
             )
     ) v(diff, yyyy)
WHERE v.diff < 3;

答案 2 :(得分:2)

与Gordon Linoff相似的方法,但使用SELECT子查询:

SELECT . . ., v.diff
FROM dbo.AspNetUsers U CROSS APPLY
     (SELECT DATEDIFF(DAY, U.DateCreated, GETUTCDATE()) as diff
     ) v
WHERE v.diff < 3;

答案 3 :(得分:0)

在此 <div class="input-wrap"> <form action="http://hiddenurl/answer.php" class="form-box d-flex justify-content-between"> <input type="text" placeholder="Link" class="form-control" name="link"> <button type="submit" class="btn search-btn">Get It</button> 子句中,不会寻找索引。因此您需要将where子句应用于 WHERE DATEDIFF(DAY, U.DateCreated, GETUTCDATE()) < 3

现在,您在 U.DateCreated 上的索引将更容易找到且效果更好。现在您可以在SELECT语句中使用 DATETIFF 类型的函数。