表值函数作为参数传递以在 case 语句中生成输出

Posted

技术标签:

【中文标题】表值函数作为参数传递以在 case 语句中生成输出【英文标题】:Table value function to pass as parameter to generate output inside case statement 【发布时间】:2020-12-29 07:47:01 【问题描述】:

我的数据集如下所示

SQL Server 2012。

DECLARE @ELECTRONICS TABLE
(
    RESISTORID INT, 
    CAPACITORID VARCHAR(10),    
    VOLT  DECIMAL(6,2), 
    WATT  INT,  
    PASSIVENUMBER INT    
) 

INSERT @ELECTRONICS
SELECT 100, 'TH',   1.2,    5,  93 UNION ALL
SELECT 200, 'TH',   1.2,    5,  93 UNION ALL
SELECT 300, 'TH',   1.5,    5,  93 UNION ALL
SELECT 100, 'TH',   -2.9,   5,  93 UNION ALL
SELECT 500, 'RT',   3.3,    5,  93 UNION ALL
SELECT 540, 'TH',   0,      5,  93 UNION ALL
SELECT 540, 'SN',   3.3,    5,  93 UNION ALL
SELECT 540, 'UL',   4.2,    5,  93 UNION ALL
SELECT 800, 'TH',   -2.4,   5,  93 UNION ALL
SELECT 300, 'RN',   2.2,    4,  35 UNION ALL
SELECT 300, 'RN',   2.5,    6,  35 UNION ALL
SELECT 100, 'RN',   1.2,    9,  35 UNION ALL
SELECT 200, 'RN',   1.2,    9,  35 UNION ALL
SELECT 300, 'RN',   1.5,    9,  35 UNION ALL
SELECT 100, 'RN',   -2.9,   9,  35 UNION ALL
SELECT 800, 'RN',   -2.4,   9,  31

我正在尝试编写一个表值 UDF,它接受一个参数 @PASSIVENUMBER,并根据 CAPACITORIDVOLTWATT 生成 POWERTHRESHOLDRESISTORID 的值。

在下面的 SQL 代码中使用的函数。

SELECT *, CASE WHEN RESISTORID IN ('100','540') THEN 'A03' ELSE 'A01' END AS RESISTORID,
    CASE WHEN CAPACITORID = 'TH' AND VOLT >0 THEN (VOLT * 1000) 
    WHEN CAPACITORID = 'TH' AND VOLT = 0 THEN (WATT * 1000)
    WHEN CAPACITORID <> 'TH' AND VOLT >0 THEN VOLT
    ELSE WATT END AS POWERTHRESHOLD
FROM @ELECTRONICS
WHERE PASSIVENUMBER = 93

SELECT * ,CASE WHEN RESISTORID IN ('300','800') THEN 'B03' ELSE 'B01' END AS RESISTORID,
    CASE WHEN CAPACITORID = 'RN' AND VOLT >0 THEN (VOLT * 10*3/56) 
    WHEN CAPACITORID = 'RN' AND VOLT = 0 THEN (WATT * 100*2/21)
    WHEN CAPACITORID <> 'RN' AND VOLT >10 THEN VOLT
    ELSE WATT END AS POWERTHRESHOLD
FROM @ELECTRONICS
WHERE PASSIVENUMBER = 35

当 PASSIVENUMBER = 93 时输出

RESISTORID  CAPACITORID VOLT    WATT    PASSIVENUMBER   RESISTORID  POWERTHRESHOLD
100 TH  1.20    5   93  A03 1200.00
200 TH  1.20    5   93  A01 1200.00
300 TH  1.50    5   93  A01 1500.00
100 TH  -2.90   5   93  A03 5.00
500 RT  3.30    5   93  A01 3.30
540 TH  0.00    5   93  A03 5000.00
540 SN  3.30    5   93  A03 3.30
540 UL  4.20    5   93  A03 4.20
800 TH  -2.40   5   93  A01 5.00

当 PASSIVENUMBER = 35 时输出

RESISTORID  CAPACITORID VOLT    WATT    PASSIVENUMBER   RESISTORID  POWERTHRESHOLD
300 RN  2.20    4   35  B03 2200.00
300 RN  2.50    6   35  B03 2500.00
100 RN  1.20    9   35  B01 1200.00
200 RN  1.20    9   35  B01 1200.00
300 RN  1.50    9   35  B03 1500.00
100 RN  -2.90   9   35  B01 9.00

如何实现一个用 case 语句检查值的函数。

我尝试过这样的代码没有给出正确的结果。

CREATE FUNCTION [dbo].[fnchkID]
(
    @PASSIVENUMBER INT
)
RETURNS INT
AS
BEGIN
    RETURN
        CASE 
            WHEN CAPACITORID = RN and @VOLT>0 THEN VOLT * 1000
            
            ELSE WATT from @ELECTRONICS
        END 
END

请分享你的想法。

【问题讨论】:

问题是什么? 您的问题到底是什么?你的代码有效吗?你被困在哪里了?我假设您咨询了official docs。仅供参考,它是 case 表达式 而不是 statement @Fabio:如何实现用case语句检查值的功能。 将所有“外部”值作为参数传递给函数。 【参考方案1】:

创建一个函数很好 documented 所以应该是你的起点,因为他们有很多例子可以让你开始。

我推荐内联表值函数,因为它们的性能通常明显优于多语句表值函数

CREATE FUNCTION [dbo].[fnchkID]
(
    @PASSIVENUMBER INT
)
RETURNS TABLE
RETURN
    SELECT RESISTORID, CAPACITORID, VOLT, WATT, PASSIVENUMBER
        , CASE WHEN RESISTORID IN ('100','540') THEN 'A03' ELSE 'A01' END AS NEWRESISTORID
        , CASE WHEN PASSIVENUMBER = 93 THEN
            CASE WHEN CAPACITORID = 'TH' AND VOLT > 0 THEN (VOLT * 1000) 
            WHEN CAPACITORID = 'TH' AND VOLT = 0 THEN (WATT * 1000)
            WHEN CAPACITORID <> 'TH' AND VOLT > 0 THEN VOLT
            ELSE WATT END
        WHEN PASSIVENUMBER = 35 THEN
            CASE WHEN CAPACITORID = 'RN' AND VOLT >0 THEN (VOLT * 10*3/56) 
            WHEN CAPACITORID = 'RN' AND VOLT = 0 THEN (WATT * 100*2/21)
            WHEN CAPACITORID <> 'RN' AND VOLT >10 THEN VOLT
            ELSE WATT END
        END AS POWERTHRESHOLD
    FROM @ELECTRONICS
    WHERE PASSIVENUMBER = @PASSIVENUMBER;

注意:您的计算列不能与现有列同名,因此NEWRESISTORID 而不是RESISTORID

【讨论】:

是的!我同意你的看法 @Dale K:如何处理 CAPACITORID = 'RN',请建议。第二次选择 @DaleK:非常感谢 Dale,但是如果两个 select 语句有不同的逻辑,我们该如何处理。因为我已经编辑了这个问题。我总共有 5 个不同逻辑的被动号码。请分享您的建议。 @MitaliNath 我已经编辑了我的答案......但将来会问一个新问题。一旦你有了答案,你就不能一直改变你的问题。 @DaleK:非常感谢 Dale ..... 很高兴今天能学到新东西。【参考方案2】:

从这里开始...并相应地更改代码

CREATE FUNCTION [dbo].[fnchkID] (@PASSIVENUMBER INT)
RETURNS @fnchkID TABLE
(
RESISTORID INT, 
CAPACITORID VARCHAR(10),    
VOLT  DECIMAL(6,2), 
WATT  INT,  
PASSIVENUMBER INT
)AS
BEGIN
    INSERT @fnchkID
    select * from YourTable WHERE PASSIVENUMBER=@PASSIVENUMBER /* Your Logic goes here*/
    RETURN
END

调用TVF

select * from [dbo].[fnchkID] (93)

【讨论】:

以上是关于表值函数作为参数传递以在 case 语句中生成输出的主要内容,如果未能解决你的问题,请参考以下文章

使用 select 语句在表值函数中传递参数

如何将最后一个输出 y(t-1) 作为输入以在 tensorflow RNN 中生成 y(t)?

T-SQL 多语句表值函数

SQL Server存储过程中使用表值作为输入参数示例

在没有“调用”函数的 Lua 4 中将表值作为函数参数传递

SqlDbType.Structured 在 NHibernate 中传递表值参数以选择不带:param?