使用Condition在SQL函数中设置变量

时间:2015-01-15 16:44:44

标签: sql-server function parameter-passing

尝试根据当前日期设置变量并传递给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)

    )

`

2 个答案:

答案 0 :(得分:4)

您根本不需要使用IF,只需制作谓词:

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

然后根本不需要@FiscalYear参数。对于它的价值,你应该在功能中改变许多其他的东西

  1. 使用表别名可以显着减少文本数量,因此您可以反复使用dbo.tbl_requirementManagement

  2. 而不是反复使用rm
  3. 您在where子句中引用外部表格会将RIGHT OUTER JOIN变为INNER JOIN,因此您也可以使用INNER JOIN。为了澄清,您有(dbo.tbl_requirementManagement.statusID = 4),所以如果tbl_requirementManagement中没有匹配,statusIDNULLNULL = 4会返回NULL,这不是真的,因此不会返回该行。

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

  5. 所以你的最终功能变为:

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

答案 1 :(得分:1)

您无法在功能if-else内进行parameter list检查。将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