使用条件在 SQL 函数中设置变量

Set Variable in SQL Function with Condition

尝试根据当前日期设置变量并传递给 SQL 函数中的查询。它在 IF 语句处出错。有什么想法吗?

  CREATE FUNCTION CS_AwaredRCPs
     (   
     @currentDate DATE,
    @fiscalYear INT

    IF DATEPART(m,@currentDate) > 10
        SET @fiscalYear = DATEPART(yyyy,@currentDate)
    ELSE
        SET @fiscalYear = DATEPART(yyyy,@currentDate) - 1
    END 
     )
    RETURNS TABLE 
    AS
    RETURN 
    (
    SELECT      dbo.tbl_requirementManagement.postaward_specialist_id, 
            SUM(dbo.tbl_requirementManagement.actual_award_value) AS    AwardValue, 
            COUNT(dbo.tbl_requirementManagement.postaward_specialist_id) AS AwardCount
    FROM        dbo.tbl_requirementManagement RIGHT OUTER JOIN
            dbo.vw_ContractSpecialists ON   dbo.tbl_requirementManagement.postaward_specialist_id = dbo.vw_ContractSpecialists.user_certificateSerialNumber
    GROUP BY    dbo.tbl_requirementManagement.statusID, dbo.tbl_requirementManagement.postaward_specialist_id, dbo.tbl_requirementManagement.fiscal_year
    HAVING     (dbo.tbl_requirementManagement.statusID = 4) AND 
           (dbo.tbl_requirementManagement.postaward_specialist_id <> 0) AND 
           (dbo.tbl_requirementManagement.fiscal_year = @fiscalYear)

    )

`

您不能在函数 parameter list 中执行 if-else 检查。将 If-else 部分移至函数 body。试试这个。

CREATE FUNCTION Cs_awaredrcps (@currentDate DATE)
RETURNS @ret_table TABLE (
  postaward_specialist_id INT,
  AwardValue              INT,
  AwardCount              INT )
AS
  BEGIN
      DECLARE @fiscalYear INT

      IF Datepart(Month, @currentDate) > 10
        SET @fiscalYear = Datepart(yyyy, @currentDate)
      ELSE
        SET @fiscalYear = Datepart(yyyy, @currentDate) - 1

      INSERT INTO @ret_table
      SELECT dbo.tbl_requirementManagement.postaward_specialist_id,
             Sum(dbo.tbl_requirementManagement.actual_award_value)        AS AwardValue,
             Count(dbo.tbl_requirementManagement.postaward_specialist_id) AS AwardCount
      FROM   dbo.tbl_requirementManagement
             RIGHT OUTER JOIN dbo.vw_ContractSpecialists
                           ON dbo.tbl_requirementManagement.postaward_specialist_id = dbo.vw_ContractSpecialists.user_certificateSerialNumber
      GROUP  BY dbo.tbl_requirementManagement.statusID,
                dbo.tbl_requirementManagement.postaward_specialist_id,
                dbo.tbl_requirementManagement.fiscal_year
      HAVING ( dbo.tbl_requirementManagement.statusID = 4 )
             AND ( dbo.tbl_requirementManagement.postaward_specialist_id <> 0 )
             AND ( dbo.tbl_requirementManagement.fiscal_year = @fiscalYear )

      RETURN
  END 

你根本不需要使用IF,你可以简单地做你的谓词:

fiscal_year = DATEPART(YEAR, @currentDate) 
                + CASE WHEN DATEPART(MONTH, @CurrentDate) <= 10 THEN -1 ELSE 0 END

那么你根本不需要 @FiscalYear 参数。对于它的价值,您还应该在函数中更改许多其他内容

  1. 使用 table 别名可以显着减少文本量,因此与其一遍又一遍地使用 dbo.tbl_requirementManagement,不如使用 rm

  2. 事实上,您在 where 子句中引用了外部 table,将您的 RIGHT OUTER JOIN 变成了 INNER JOIN,因此您也可以只使用和 INNER JOIN。澄清一下,您有 (dbo.tbl_requirementManagement.statusID = 4),因此在 tbl_requirementManagement 中没有匹配项的地方,statusID 将是 NULL,而 NULL = 4 returns NULL,这是不正确的,因此不会返回该行。

  3. 您的谓词不引用聚合,因此应该在 WHERE 子句中,而不是 HAVING

因此您的最终函数变为:

CREATE FUNCTION CS_AwaredRCPs (@currentDate DATE)
RETURNS TABLE
AS
RETURN
(   SELECT  rm.postaward_specialist_id,
            SUM(rm.actual_award_value) AS AwardValue, 
            COUNT(rm.postaward_specialist_id) AS AwardCount
    FROM    dbo.tbl_requirementManagement AS rm
            INNER JOIN dbo.vw_ContractSpecialists AS cs
                ON rm.postaward_specialist_id = cs.user_certificateSerialNumber 
    WHERE   rm.fiscal_year = DATEPART(YEAR,@currentDate) 
                                + CASE WHEN DATEPART(MONTH, @CurrentDate) <= 10 THEN -1 ELSE 0 END
    AND     rm.statusID = 4
    AND     rm.postaward_specialist_id <> 0
    GROUP BY rm.statusID, rm.postaward_specialist_id, rm.fiscal_year
);