1

SQL 新手,经验丰富的 VBA-er 需要一些帮助。

我对需要获得特定类型的一些不同费用的交易有看法。费用在表格中,其中一些字段是必需的,而其他字段可能为 NULL。通过这种方式,我们可以获得一个通用的费用结构,并且仍然允许特定的特价。

我现在的目标是找到最佳匹配费用。这是以下费用:

  1. 符合所有要求的标准,
  2. 匹配所有可选条件或NULL为它们提供,
  3. 具有通过 1. 和 2 的所有费用中最匹配的可选标准。

现在我得到了这个代码的一个版本,但作为一个过程。但是,由于我需要在视图中使用它,因此我无法使用该版本,并且函数中不允许使用临时表)。

在查看了这个论坛和其他人之后,我得出一个仍然给出 2 个错误的结果:
1. ErrorMessage: Incorrect syntax near '@tblTEMP'
2. ErrorMessage: Incorrect syntax near 'BEGIN'

我当前的脚本如下(使用局部变量表):

ALTER FUNCTION [dbo].[fnStandardFeeBAK]
  (@Type_Id BIGINT, @Party_Id BIGINT, @I_A_Id BIGINT, @Grid_Id BIGINT,
  @Market_Id BIGINT, @Counterparty_Id BIGINT, @Product_Id BIGINT, 
  @DealDate DATETIME)
RETURNS TABLE

AS

BEGIN
  DECLARE @tblTEMP TABLE (Standard_Fee DECIMAL(38,8), Currency VARCHAR(50), 
  Unit VARCHAR(50), Unit2 VARCHAR(50), MatchScore BIGINT);
  WITH @tblTEMP AS 
  (SELECT Standard_Fee, V2.Element AS Currency, V1.Element AS Unit,
V2.Element+'/'+V1.Element AS Unit2,
  SF.I_A_Id, SF.Grid_Id, SF.Product_Id, SF.Counterparty_Id,
  (CASE WHEN SF.I_A_Id = @I_A_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Grid_Id = @Grid_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Product_Id = @Product_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Counterparty_Id = @Counterparty_Id THEN 1 ELSE 0 END) 
      AS MatchScore
  FROM tblStandard_Fee AS SF
  LEFT JOIN tblElement AS V1 ON V1.Element_Id = SF.Unit_Id
  LEFT JOIN tblElement AS V2 ON V2.Element_Id = SF.Currency_Id

  WHERE SF.Type_Id = @Type_Id AND SF.Party_Id = @Party_Id AND 
    SF.Market_Id = @Market_Id
    AND SF.Date_From < @DealDate 
    AND (SF.Date_To > @DealDate OR SF.Date_To IS NULL)
    AND (SF.I_A_Id = @I_A_Id OR SF.I_A_Id IS NULL)
    AND (SF.Grid_Id = @Grid_Id OR SF.Grid_Id IS NULL)
    AND (SF.Product_Id = @Product_Id OR SF.Product_Id IS NULL)
    AND (SF.Counterparty_Id = @Counterparty_Id OR SF.Counterparty_Id IS NULL))
RETURN
  SELECT Standard_Fee, Currency, Unit, Unit2
  FROM @tblTEMP
  WHERE MatchScore= MAX(MatchScore)
END

如果不让我知道,我希望我的问题很清楚。

感谢您提出建议,甚至用最后一点解决我的问题!


所以 LittleBobbyTables 的所有帮助结合起来给了我一个工作的最终结果。请不要忘记给他学分。

工作代码:

ALTER FUNCTION [dbo].[fnStandardFeeBAK]
(@Type_Id BIGINT, @Party_Id BIGINT, @I_A_Id BIGINT, @Grid_Id BIGINT,
@Market_Id BIGINT, @Counterparty_Id BIGINT, @Product_Id BIGINT, @DealDate DATETIME)

RETURNS @YourTable TABLE 
(
    -- Columns returned by the function
    Standard_Fee DECIMAL(38,8), 
    Currency VARCHAR(50), 
    Unit VARCHAR(50), 
    Unit2 VARCHAR(50)
)
AS

BEGIN   
    WITH YourCTE(Standard_Fee, Currency, Unit, Unit2, MatchScore) AS
    (
    SELECT Standard_Fee, V2.Element AS Currency, V1.Element AS Unit,
        V2.Element + '/' + V1.Element AS Unit2,
        (CASE WHEN SF.I_A_Id = @I_A_Id THEN 1 ELSE 0 END +
        CASE WHEN SF.Grid_Id = @Grid_Id THEN 1 ELSE 0 END +
        CASE WHEN SF.Product_Id = @Product_Id THEN 1 ELSE 0 END +
        CASE WHEN SF.Counterparty_Id = @Counterparty_Id THEN 1 ELSE 0 END) 
        AS MatchScore
    FROM tblStandard_Fee AS SF
        LEFT JOIN tblElement AS V1 ON V1.Element_Id = SF.Unit_Id
        LEFT JOIN tblElement AS V2 ON V2.Element_Id = SF.Currency_Id

    --Type_ID, Party_ID and Market_Id are always present, others can have NULL values
    WHERE SF.Type_Id = @Type_Id AND SF.Party_Id = @Party_Id 
            AND SF.Market_Id = @Market_Id AND SF.Date_From < @DealDate 
            AND (SF.Date_To > @DealDate OR SF.Date_To IS NULL)
            AND (SF.I_A_Id = @I_A_Id OR SF.I_A_Id IS NULL)
            AND (SF.Grid_Id = @Grid_Id OR SF.Grid_Id IS NULL)
            AND (SF.Product_Id = @Product_Id OR SF.Product_Id IS NULL)
            AND (SF.Counterparty_Id = @Counterparty_Id OR SF.Counterparty_Id IS NULL)
    GROUP BY Standard_Fee, V1.Element, V2.Element, SF.I_A_Id, SF.Grid_Id, SF.Product_Id, SF.Counterparty_Id
    )
    INSERT @YourTable 
        SELECT Standard_Fee, Currency, Unit, Unit2
        FROM YourCTE 
        GROUP BY MatchScore, Standard_Fee, Currency, Unit, Unit2
        HAVING MatchScore = (SELECT MAX(MatchScore) FROM YourCTE)

     RETURN;
END
4

1 回答 1

2

请参阅Table-Valued User-Defined Functions文档,正确的语法是:

ALTER FUNCTION dbo.fnStandardFeeBAK(@Type_Id BIGINT, @Party_Id BIGINT, 
    @I_A_Id BIGINT, @Grid_Id BIGINT,  @Market_Id BIGINT, 
    @Counterparty_Id BIGINT, @Product_Id BIGINT, 
    @DealDate DATETIME)

RETURNS @YourTable TABLE 
(
    -- Columns returned by the function
    Standard_Fee DECIMAL(38,8), 
    Currency VARCHAR(50), 
    Unit VARCHAR(50), 
    Unit2 VARCHAR(50)
)
AS

最后:

    INSERT @YourTable 
    SELECT Standard_Fee, Currency, Unit, Unit2
    FROM YourCTE
    WHERE MatchScore= MAX(MatchScore)
    RETURN;
END;

编辑:搞砸了 CTE,你不需要临时表。

把它们放在一起,你会得到:

ALTER FUNCTION dbo.fnStandardFeeBAK(@Type_Id BIGINT, @Party_Id BIGINT, 
    @I_A_Id BIGINT, @Grid_Id BIGINT,  @Market_Id BIGINT, 
    @Counterparty_Id BIGINT, @Product_Id BIGINT, 
    @DealDate DATETIME)

RETURNS @YourTable TABLE 
(
    -- Columns returned by the function
    Standard_Fee DECIMAL(38,8), 
    Currency VARCHAR(50), 
    Unit VARCHAR(50), 
    Unit2 VARCHAR(50)
)
AS

BEGIN
 WITH YourCTE (Standard_Fee, Currency, Unit, Unit2, MatchScore) AS 
  (SELECT Standard_Fee, V2.Element AS Currency, V1.Element AS Unit,
V2.Element+'/'+V1.Element AS Unit2,
  SF.I_A_Id, SF.Grid_Id, SF.Product_Id, SF.Counterparty_Id,
  (CASE WHEN SF.I_A_Id = @I_A_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Grid_Id = @Grid_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Product_Id = @Product_Id THEN 1 ELSE 0 END +
      CASE WHEN SF.Counterparty_Id = @Counterparty_Id THEN 1 ELSE 0 END) 
      AS MatchScore
  FROM tblStandard_Fee AS SF
  LEFT JOIN tblElement AS V1 ON V1.Element_Id = SF.Unit_Id
  LEFT JOIN tblElement AS V2 ON V2.Element_Id = SF.Currency_Id

  WHERE SF.Type_Id = @Type_Id AND SF.Party_Id = @Party_Id AND 
    SF.Market_Id = @Market_Id
    AND SF.Date_From < @DealDate 
    AND (SF.Date_To > @DealDate OR SF.Date_To IS NULL)
    AND (SF.I_A_Id = @I_A_Id OR SF.I_A_Id IS NULL)
    AND (SF.Grid_Id = @Grid_Id OR SF.Grid_Id IS NULL)
    AND (SF.Product_Id = @Product_Id OR SF.Product_Id IS NULL)
    AND (SF.Counterparty_Id = @Counterparty_Id OR SF.Counterparty_Id IS NULL))

  INSERT @YourTable 
    SELECT Standard_Fee, Currency, Unit, Unit2
    FROM YourCTE
    WHERE MatchScore= MAX(MatchScore)
  RETURN;
END;
于 2012-08-08T13:28:28.000 回答