【问题标题】:T-SQL User Defined Function or similar to calculate Max Value (Date) from a list of valuesT-SQL 用户定义函数或类似函数,用于从值列表中计算最大值(日期)
【发布时间】:2012-12-18 05:03:59
【问题描述】:

假设我有一个来源,我必须像这样查询:

Select Fields 
from TableA A
join TableB B on A.SomeField = B.SomeField
join TableC C on B.SomeField = C.SomeField
Join TableD D on C.SomeField = D.SomeField
Where 
    CustomMaxDateFunction (A.SomeDateField, B.SomeDateField, C.SomeDateField, D.SomeDateField) > '20130101 23:59:00'

我知道我可以将 where 子句写成如下内容,但我不想这样做:

Where 
  A.SomeDateField > '20130101 23:59:00' 
  OR B.SomeDateField > '20130101 23:59:00' 
  OR C.SomeDateField > '20130101 23:59:00' 
  OR D.SomeDateField > '20130101 23:59:00'

请记住,要比较的列数会根据连接中源表的数量而变化。

由于我们将不得不重复使用自定义函数(或存储过程),所以关于最简单的方法的任何建议。

【问题讨论】:

  • 我知道这是一个示例查询 - 但 Join TableD D on A.SomeField = B.SomeField 不对。
  • 哎呀,你是对的。对不起,我正在复制和粘贴。我会解决的。

标签: sql-server tsql stored-procedures user-defined-functions sql-server-2012


【解决方案1】:

您可以只使用内置的 MAX 聚合,而不是创建新函数。

SELECT MAX(v) FROM (VALUES(A.SomeDateField),(B.SomeDateFiled),(C.SomeDateField),(D.SomeDateField))dates(v)

或在您的查询上下文中:

SELECT *
FROM TableA AS A
JOIN TableB AS B
ON ...
JOIN TableC AS C
ON ...
JOIN TableD AS D
ON ...
WHERE (SELECT MAX(v) FROM (VALUES(A.SomeDateField),(B.SomeDateFiled),(C.SomeDateField),(D.SomeDateField))dates(v)) > '20130101 23:59:00'

如果不够干净,你可以把它包装成一个函数

CREATE FUNCTION dbo.CustomMaxDateFunction(@v1 DATETIME, @v2 DATETIME, @v3 DATETIME, @v4 DATETIME)
RETURNS TABLE
AS
  RETURN SELECT MAX(v) MaxDate FROM (VALUES(@v1),(@v2),(@v3),(@v4))dates(v);

然后这样称呼它:

SELECT *
FROM TableA AS A
JOIN TableB AS B
ON ...
JOIN TableC AS C
ON ...
JOIN TableD AS D
ON ...
CROSS APPLY dbo.CustomMaxDateFunction(A.SomeDateField, B.SomeDateFiled, C.SomeDateField, D.SomeDateField) AS mdf
WHERE mdf.MaxDate > '20130101 23:59:00'

在此查询上下文中远离其他形式的函数,因为它们会损害性能: http://sqlity.net/en/498/t-sql-tuesday-24-prox-n-funx/

然而,所有函数都有一个共同点,即您固定使用给定数量的参数,因此第一个选项可能是您最好的选择。

编辑: 如果你真的喜欢函数的想法,你可以这样做:

CREATE FUNCTION dbo.CustomMaxDateFunction(@v1 DATETIME, @v2 DATETIME, @v3 DATETIME, @v4 DATETIME)
    RETURNS TABLE
    AS
      RETURN SELECT MAX(v) MaxDate FROM (VALUES(@v1),(@v2),(@v3),(@v4))dates(v) WHERE v IS NOT NULL;

现在你可以这样称呼它:

SELECT *
FROM TableA AS A
JOIN TableB AS B
ON ...
CROSS APPLY dbo.CustomMaxDateFunction(A.SomeDateField, B.SomeDateFiled, NULL, NULL) AS mdf
WHERE mdf.MaxDate > '20130101 23:59:00'

您实际上必须用 NULL 填充未使用的参数。函数中的附加 WHERE 子句可防止您收到有关已消除 NULL 值的警告。正如 RBarryYoung 在 cmets 中提到的,SQL Server 中的函数没有真正的可选参数功能。

【讨论】:

  • 我可以用很多参数做一些事情,但它们是可选的吗?
  • @DavidStein 可选参数在 T-SQL 中无法正常工作。你可以定义它们,但是当你调用函数时你必须用一个参数填充每个参数,或者把 default 放在它的位置。完全没用。
  • 顺便说一句。支持找到两种不同的方法来做到这一点,从而避免在这个例子中标量函数会产生可怕的性能损失。
猜你喜欢
  • 1970-01-01
  • 2015-08-08
  • 2023-03-10
  • 1970-01-01
  • 2019-10-24
  • 2020-09-29
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多