将 table 和 return 和 table 传递给存储过程或函数?
Pass a table and return a table to a stored procedure or function?
我想将 table 传递给 UDF 或存储过程,然后让它处理数据和 return 灵敏度、特异性和 95% Upper/Lower 置信区间(对于每个)从 table 我传递给它。
基本上,从 table 我需要计算和 return 六个值。
我必须多次这样做,所以自动化会很棒,但我还没有创建 UDF 或 SP。我已经阅读了它们(Whosebug 和其他地方,但我仍然不知道如何进行。
我创建了 SQL 部分来计算感兴趣的参数,但我真的很困惑如何将 table 传递给它并返回 table。
DECLARE @R_MODS TABLE(
SUBJECTID varchar(max),
ResultCall varchar(max)
)
INSERT INTO @R_MODS VALUES ('11-0001','TP');
INSERT INTO @R_MODS VALUES ('11-0002','TP');
INSERT INTO @R_MODS VALUES ('11-0003','TP');
INSERT INTO @R_MODS VALUES ('11-0004','TP');
INSERT INTO @R_MODS VALUES ('11-0005','TP');
INSERT INTO @R_MODS VALUES ('11-0006','I');
INSERT INTO @R_MODS VALUES ('11-0007','TP');
INSERT INTO @R_MODS VALUES ('11-0008','TP');
INSERT INTO @R_MODS VALUES ('11-0009','I');
INSERT INTO @R_MODS VALUES ('11-0010','TP');
INSERT INTO @R_MODS VALUES ('11-0011','TP');
INSERT INTO @R_MODS VALUES ('11-0012','TN');
INSERT INTO @R_MODS VALUES ('11-0013','TP');
INSERT INTO @R_MODS VALUES ('11-0014','I');
INSERT INTO @R_MODS VALUES ('11-0015','TP');
INSERT INTO @R_MODS VALUES ('11-0016','TP');
INSERT INTO @R_MODS VALUES ('11-0017','TN');
INSERT INTO @R_MODS VALUES ('11-0018','TP');
INSERT INTO @R_MODS VALUES ('11-0019','FP');
INSERT INTO @R_MODS VALUES ('11-0020','FP');
DECLARE @TP float, @TN float, @FP float, @FN float, @SEN float, @SPE float, @M1 float,
@M2 float, @Sen95 float, @SpeL float , @SpeU float, @SenU float, @SenL float
SET @TP = (SELECT COUNT(SUBJECTID) FROM @R_MODS WHERE ResultCall='TP')
SET @TN = (SELECT COUNT(SUBJECTID) FROM @R_MODS WHERE ResultCall='TN')
SET @FP = (SELECT COUNT(SUBJECTID) FROM @R_MODS WHERE ResultCall='FP')
SET @FN = (SELECT COUNT(SUBJECTID) FROM @R_MODS WHERE ResultCall='FN')
SET @SEN = @TP/(@TP + @FN)
SET @M1 = @TP + @FN
SET @SPE = @TN/(@TN + @FP)
SET @M2 = @FP + @TN
SET @SenL = ( 2*@M1*@SEN + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2)
- 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) + 1)))/(2*(@M1+POWER(1.96,2)))
SET @SenU = ( 2*@M1*@SEN + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2)
+ 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) - 1)))/(2*(@M1+POWER(1.96,2)))
SET @SpeL = ( 2*@M2*@SPE + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2)
- 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) + 1)))/(2*(@M2+POWER(1.96,2)))
SET @SpeU = ( 2*@M2*@SPE + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2)
+ 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) - 1)))/(2*(@M2+POWER(1.96,2)))
SELECT @SEN, @SenL, @SenU, 1-@SPE, 1-@SPEL, 1-@SpeU
由于您的代码只是对数据进行计算(即没有 tables 的副作用或更新)并且没有耦合到 tables,您可以做的是创建table valued function to do these calculations - the function can take in the table of inputs (R_MODS
)as a table type 和 return 输出的 table(Sen
等)。
这里是 SqlFiddle example。
详细:
您需要为输入创建一个 table 类型,例如
CREATE TYPE R_MODS_TYPE AS TABLE(
SUBJECTID varchar(max),
ResultCall varchar(max)
);
并这样定义函数:
CREATE FUNCTION dbo.DoCalcs(@TheRMods R_MODS_TYPE READONLY)
RETURNS @Result TABLE
(
[SEN] DECIMAL(10,4),
[SenL] DECIMAL(10,4),
[SenU] DECIMAL(10,4),
[1-SPE] DECIMAL(10,4),
[1-SPEL] DECIMAL(10,4),
[1-SpeU] DECIMAL(10,4)
)
AS
BEGIN
DECLARE @TP float, @TN float, @FP float, @FN float, @SEN float, @SPE float,
@M1 float, @M2 float, @Sen95 float, @SpeL float , @SpeU float,
@SenU float, @SenL float;
SET @TP = (SELECT COUNT(SUBJECTID) FROM @TheRMods WHERE ResultCall='TP')
SET @TN = (SELECT COUNT(SUBJECTID) FROM @TheRMods WHERE ResultCall='TN')
SET @FP = (SELECT COUNT(SUBJECTID) FROM @TheRMods WHERE ResultCall='FP')
SET @FN = (SELECT COUNT(SUBJECTID) FROM @TheRMods WHERE ResultCall='FN')
SET @SEN = @TP/(@TP + @FN)
SET @M1 = @TP + @FN
SET @SPE = @TN/(@TN + @FP)
SET @M2 = @FP + @TN
SET @SenL = ( 2*@M1*@SEN + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2)
- 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) + 1)))/(2*(@M1+POWER(1.96,2)))
SET @SenU = ( 2*@M1*@SEN + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2)
+ 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) - 1)))/(2*(@M1+POWER(1.96,2)))
SET @SpeL = ( 2*@M2*@SPE + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2)
- 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) + 1)))/(2*(@M2+POWER(1.96,2)))
SET @SpeU = ( 2*@M2*@SPE + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2)
+ 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) - 1)))/(2*(@M2+POWER(1.96,2)))
INSERT INTO @Result ([SEN], [SenL], [SenU], [1-SPE], [1-SPEL], [1-SpeU])
SELECT @SEN, @SenL, @SenU, 1-@SPE, 1-@SPEL, 1-@SpeU;
RETURN;
END
然后您通过声明 table 类型的实例、填充它并将其传递给您的函数来调用 table 函数:
DECLARE @TestData R_MODS_TYPE;
INSERT INTO @TestData VALUES ('11-0001','TP'),
('11-0002','TP'),
('11-0003','TP'),
('11-0004','TP'),
... etc.
SELECT * FROM dbo.DoCalcs(@TestData);
结果:
SEN SenL SenU 1-SPE 1-SPEL 1-SpeU
--------- -------- ------- ------- ------- -------
1.0000 0.7166 0.9929 0.5000 0.9081 0.0919
这是另一种使用 Stored Procedure
的方法
您的输入参数需要用户定义的 table 数据类型。
CREATE TYPE R_MODS_TBL AS TABLE(
SUBJECTID VARCHAR(MAX),
ResultCall VARCHAR(MAX)
)
和存储过程:
注意变量赋值的变化 @TP
、@TN
、@FP
和 @FN
使用单个 SELECT
语句而不是四个单独的语句。
CREATE PROCEDURE dbo.YourStoredProcedure(
@R_MODS R_MODS_TBL READONLY
)
AS
DECLARE
@TP FLOAT, @TN FLOAT, @FP FLOAT, @FN FLOAT,
@SEN FLOAT, @SPE FLOAT, @M1 FLOAT, @M2 FLOAT, @Sen95 FLOAT,
@SpeL FLOAT, @SpeU FLOAT, @SenU FLOAT, @SenL FLOAT
SELECT
@TP = COUNT(CASE WHEN ResultCall='TP' THEN SUBJECTID END),
@TN = COUNT(CASE WHEN ResultCall='TN' THEN SUBJECTID END),
@FP = COUNT(CASE WHEN ResultCall='FP' THEN SUBJECTID END),
@FN = COUNT(CASE WHEN ResultCall='FN' THEN SUBJECTID END)
FROM @R_MODS
SET @SEN = @TP/(@TP + @FN)
SET @M1 = @TP + @FN
SET @SPE = @TN/(@TN + @FP)
SET @M2 = @FP + @TN
SET @SenL = (2*@M1*@SEN + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2) - 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) + 1)))/(2*(@M1+POWER(1.96,2)))
SET @SenU = (2*@M1*@SEN + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2) + 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) - 1)))/(2*(@M1+POWER(1.96,2)))
SET @SpeL = (2*@M2*@SPE + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2) - 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) + 1)))/(2*(@M2+POWER(1.96,2)))
SET @SpeU = (2*@M2*@SPE + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2) + 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) - 1)))/(2*(@M2+POWER(1.96,2)))
SELECT @SEN, @SenL, @SenU, 1-@SPE, 1-@SPEL, 1-@SpeU
要执行存储过程,您想要填充生成的用户定义 table 数据类型的实例:
DECLARE @R_MODS R_MODS_TBL
INSERT INTO @R_MODS VALUES ('11-0001','TP');
INSERT INTO @R_MODS VALUES ('11-0002','TP');
INSERT INTO @R_MODS VALUES ('11-0003','TP');
INSERT INTO @R_MODS VALUES ('11-0004','TP');
INSERT INTO @R_MODS VALUES ('11-0005','TP');
INSERT INTO @R_MODS VALUES ('11-0006','I');
INSERT INTO @R_MODS VALUES ('11-0007','TP');
INSERT INTO @R_MODS VALUES ('11-0008','TP');
INSERT INTO @R_MODS VALUES ('11-0009','I');
INSERT INTO @R_MODS VALUES ('11-0010','TP');
INSERT INTO @R_MODS VALUES ('11-0011','TP');
INSERT INTO @R_MODS VALUES ('11-0012','TN');
INSERT INTO @R_MODS VALUES ('11-0013','TP');
INSERT INTO @R_MODS VALUES ('11-0014','I');
INSERT INTO @R_MODS VALUES ('11-0015','TP');
INSERT INTO @R_MODS VALUES ('11-0016','TP');
INSERT INTO @R_MODS VALUES ('11-0017','TN');
INSERT INTO @R_MODS VALUES ('11-0018','TP');
INSERT INTO @R_MODS VALUES ('11-0019','FP');
INSERT INTO @R_MODS VALUES ('11-0020','FP');
EXEC dbo.YourStoredProcedure @R_MODS
注:
在存储过程中使用取值为table的输入参数时,需要将参数声明为READONLY
。阅读 Mikael Eriksson 撰写的 answer 了解更多信息。
我想将 table 传递给 UDF 或存储过程,然后让它处理数据和 return 灵敏度、特异性和 95% Upper/Lower 置信区间(对于每个)从 table 我传递给它。
基本上,从 table 我需要计算和 return 六个值。
我必须多次这样做,所以自动化会很棒,但我还没有创建 UDF 或 SP。我已经阅读了它们(Whosebug 和其他地方,但我仍然不知道如何进行。
我创建了 SQL 部分来计算感兴趣的参数,但我真的很困惑如何将 table 传递给它并返回 table。
DECLARE @R_MODS TABLE(
SUBJECTID varchar(max),
ResultCall varchar(max)
)
INSERT INTO @R_MODS VALUES ('11-0001','TP');
INSERT INTO @R_MODS VALUES ('11-0002','TP');
INSERT INTO @R_MODS VALUES ('11-0003','TP');
INSERT INTO @R_MODS VALUES ('11-0004','TP');
INSERT INTO @R_MODS VALUES ('11-0005','TP');
INSERT INTO @R_MODS VALUES ('11-0006','I');
INSERT INTO @R_MODS VALUES ('11-0007','TP');
INSERT INTO @R_MODS VALUES ('11-0008','TP');
INSERT INTO @R_MODS VALUES ('11-0009','I');
INSERT INTO @R_MODS VALUES ('11-0010','TP');
INSERT INTO @R_MODS VALUES ('11-0011','TP');
INSERT INTO @R_MODS VALUES ('11-0012','TN');
INSERT INTO @R_MODS VALUES ('11-0013','TP');
INSERT INTO @R_MODS VALUES ('11-0014','I');
INSERT INTO @R_MODS VALUES ('11-0015','TP');
INSERT INTO @R_MODS VALUES ('11-0016','TP');
INSERT INTO @R_MODS VALUES ('11-0017','TN');
INSERT INTO @R_MODS VALUES ('11-0018','TP');
INSERT INTO @R_MODS VALUES ('11-0019','FP');
INSERT INTO @R_MODS VALUES ('11-0020','FP');
DECLARE @TP float, @TN float, @FP float, @FN float, @SEN float, @SPE float, @M1 float,
@M2 float, @Sen95 float, @SpeL float , @SpeU float, @SenU float, @SenL float
SET @TP = (SELECT COUNT(SUBJECTID) FROM @R_MODS WHERE ResultCall='TP')
SET @TN = (SELECT COUNT(SUBJECTID) FROM @R_MODS WHERE ResultCall='TN')
SET @FP = (SELECT COUNT(SUBJECTID) FROM @R_MODS WHERE ResultCall='FP')
SET @FN = (SELECT COUNT(SUBJECTID) FROM @R_MODS WHERE ResultCall='FN')
SET @SEN = @TP/(@TP + @FN)
SET @M1 = @TP + @FN
SET @SPE = @TN/(@TN + @FP)
SET @M2 = @FP + @TN
SET @SenL = ( 2*@M1*@SEN + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2)
- 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) + 1)))/(2*(@M1+POWER(1.96,2)))
SET @SenU = ( 2*@M1*@SEN + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2)
+ 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) - 1)))/(2*(@M1+POWER(1.96,2)))
SET @SpeL = ( 2*@M2*@SPE + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2)
- 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) + 1)))/(2*(@M2+POWER(1.96,2)))
SET @SpeU = ( 2*@M2*@SPE + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2)
+ 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) - 1)))/(2*(@M2+POWER(1.96,2)))
SELECT @SEN, @SenL, @SenU, 1-@SPE, 1-@SPEL, 1-@SpeU
由于您的代码只是对数据进行计算(即没有 tables 的副作用或更新)并且没有耦合到 tables,您可以做的是创建table valued function to do these calculations - the function can take in the table of inputs (R_MODS
)as a table type 和 return 输出的 table(Sen
等)。
这里是 SqlFiddle example。
详细:
您需要为输入创建一个 table 类型,例如
CREATE TYPE R_MODS_TYPE AS TABLE(
SUBJECTID varchar(max),
ResultCall varchar(max)
);
并这样定义函数:
CREATE FUNCTION dbo.DoCalcs(@TheRMods R_MODS_TYPE READONLY)
RETURNS @Result TABLE
(
[SEN] DECIMAL(10,4),
[SenL] DECIMAL(10,4),
[SenU] DECIMAL(10,4),
[1-SPE] DECIMAL(10,4),
[1-SPEL] DECIMAL(10,4),
[1-SpeU] DECIMAL(10,4)
)
AS
BEGIN
DECLARE @TP float, @TN float, @FP float, @FN float, @SEN float, @SPE float,
@M1 float, @M2 float, @Sen95 float, @SpeL float , @SpeU float,
@SenU float, @SenL float;
SET @TP = (SELECT COUNT(SUBJECTID) FROM @TheRMods WHERE ResultCall='TP')
SET @TN = (SELECT COUNT(SUBJECTID) FROM @TheRMods WHERE ResultCall='TN')
SET @FP = (SELECT COUNT(SUBJECTID) FROM @TheRMods WHERE ResultCall='FP')
SET @FN = (SELECT COUNT(SUBJECTID) FROM @TheRMods WHERE ResultCall='FN')
SET @SEN = @TP/(@TP + @FN)
SET @M1 = @TP + @FN
SET @SPE = @TN/(@TN + @FP)
SET @M2 = @FP + @TN
SET @SenL = ( 2*@M1*@SEN + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2)
- 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) + 1)))/(2*(@M1+POWER(1.96,2)))
SET @SenU = ( 2*@M1*@SEN + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2)
+ 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) - 1)))/(2*(@M1+POWER(1.96,2)))
SET @SpeL = ( 2*@M2*@SPE + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2)
- 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) + 1)))/(2*(@M2+POWER(1.96,2)))
SET @SpeU = ( 2*@M2*@SPE + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2)
+ 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) - 1)))/(2*(@M2+POWER(1.96,2)))
INSERT INTO @Result ([SEN], [SenL], [SenU], [1-SPE], [1-SPEL], [1-SpeU])
SELECT @SEN, @SenL, @SenU, 1-@SPE, 1-@SPEL, 1-@SpeU;
RETURN;
END
然后您通过声明 table 类型的实例、填充它并将其传递给您的函数来调用 table 函数:
DECLARE @TestData R_MODS_TYPE;
INSERT INTO @TestData VALUES ('11-0001','TP'),
('11-0002','TP'),
('11-0003','TP'),
('11-0004','TP'),
... etc.
SELECT * FROM dbo.DoCalcs(@TestData);
结果:
SEN SenL SenU 1-SPE 1-SPEL 1-SpeU
--------- -------- ------- ------- ------- -------
1.0000 0.7166 0.9929 0.5000 0.9081 0.0919
这是另一种使用 Stored Procedure
您的输入参数需要用户定义的 table 数据类型。
CREATE TYPE R_MODS_TBL AS TABLE(
SUBJECTID VARCHAR(MAX),
ResultCall VARCHAR(MAX)
)
和存储过程:
注意变量赋值的变化 @TP
、@TN
、@FP
和 @FN
使用单个 SELECT
语句而不是四个单独的语句。
CREATE PROCEDURE dbo.YourStoredProcedure(
@R_MODS R_MODS_TBL READONLY
)
AS
DECLARE
@TP FLOAT, @TN FLOAT, @FP FLOAT, @FN FLOAT,
@SEN FLOAT, @SPE FLOAT, @M1 FLOAT, @M2 FLOAT, @Sen95 FLOAT,
@SpeL FLOAT, @SpeU FLOAT, @SenU FLOAT, @SenL FLOAT
SELECT
@TP = COUNT(CASE WHEN ResultCall='TP' THEN SUBJECTID END),
@TN = COUNT(CASE WHEN ResultCall='TN' THEN SUBJECTID END),
@FP = COUNT(CASE WHEN ResultCall='FP' THEN SUBJECTID END),
@FN = COUNT(CASE WHEN ResultCall='FN' THEN SUBJECTID END)
FROM @R_MODS
SET @SEN = @TP/(@TP + @FN)
SET @M1 = @TP + @FN
SET @SPE = @TN/(@TN + @FP)
SET @M2 = @FP + @TN
SET @SenL = (2*@M1*@SEN + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2) - 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) + 1)))/(2*(@M1+POWER(1.96,2)))
SET @SenU = (2*@M1*@SEN + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2) + 2 -(1/@M1)+ 4*@SEN *(@M1*(1-@SEN) - 1)))/(2*(@M1+POWER(1.96,2)))
SET @SpeL = (2*@M2*@SPE + POWER(1.96,2) - 1 - 1.96 * SQRT(POWER(1.96,2) - 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) + 1)))/(2*(@M2+POWER(1.96,2)))
SET @SpeU = (2*@M2*@SPE + POWER(1.96,2) + 1 + 1.96 * SQRT(POWER(1.96,2) + 2 -(1/@M2)+ 4*@SPE *(@M2*(1-@SPE) - 1)))/(2*(@M2+POWER(1.96,2)))
SELECT @SEN, @SenL, @SenU, 1-@SPE, 1-@SPEL, 1-@SpeU
要执行存储过程,您想要填充生成的用户定义 table 数据类型的实例:
DECLARE @R_MODS R_MODS_TBL
INSERT INTO @R_MODS VALUES ('11-0001','TP');
INSERT INTO @R_MODS VALUES ('11-0002','TP');
INSERT INTO @R_MODS VALUES ('11-0003','TP');
INSERT INTO @R_MODS VALUES ('11-0004','TP');
INSERT INTO @R_MODS VALUES ('11-0005','TP');
INSERT INTO @R_MODS VALUES ('11-0006','I');
INSERT INTO @R_MODS VALUES ('11-0007','TP');
INSERT INTO @R_MODS VALUES ('11-0008','TP');
INSERT INTO @R_MODS VALUES ('11-0009','I');
INSERT INTO @R_MODS VALUES ('11-0010','TP');
INSERT INTO @R_MODS VALUES ('11-0011','TP');
INSERT INTO @R_MODS VALUES ('11-0012','TN');
INSERT INTO @R_MODS VALUES ('11-0013','TP');
INSERT INTO @R_MODS VALUES ('11-0014','I');
INSERT INTO @R_MODS VALUES ('11-0015','TP');
INSERT INTO @R_MODS VALUES ('11-0016','TP');
INSERT INTO @R_MODS VALUES ('11-0017','TN');
INSERT INTO @R_MODS VALUES ('11-0018','TP');
INSERT INTO @R_MODS VALUES ('11-0019','FP');
INSERT INTO @R_MODS VALUES ('11-0020','FP');
EXEC dbo.YourStoredProcedure @R_MODS
注:
在存储过程中使用取值为table的输入参数时,需要将参数声明为READONLY
。阅读 Mikael Eriksson 撰写的 answer 了解更多信息。