0

目前,此游标需要很多次才能执行。而且我相信最好的解决方案是将光标转换为SELECT语句。我已经实现了一些选择语句,但无法将父表的值作为参数发送到第二个表返回函数。你知道我怎样才能用SELECT语句得到完全相同的结果吗?

这是原始CURSOR实现

declare @orgusers table (UserID int, PRIMARY KEY (UserID))
                delete from @orgusers
                declare curOrgs CURSOR FAST_FORWARD FOR
                    select distinct ('~' + qlu.MemberValue + '~') as curOrgs                    
                    FROM [gl].VTN_QualificationMemberLU qlu 
                    where qlu.MemberType = 45 and qlu.QualificationID = 1111
                open curOrgs
                FETCH NEXT FROM curOrgs INTO @org
                while @@FETCH_STATUS = 0
                begin
                    insert into @orgusers(UserID) 
                    SELECT distinct u.UserID
                    FROM [gl].[GetStudentsByOUPath_BeforeCutoff](@nCompanyid, @org, @dCutOffDate) as u
                    left join @orgusers ou on ou.UserID = u.UserID
                    where ou.UserID is null
                    fetch next from curOrgs INTO @org
                end 
                close curOrgs
                deallocate curOrgs  

我正在寻找一种方法来将其转换CURSORSELECT语句以IDs@orgusers TABLE.

要重现的场景。

qlu.MemberValue 从表中返回数据,称为VTN_QualificationMemberLU-2343-2987-2783-2873

因此,基于 MemberValue 调用的函数GetStudentsByOUPath_BeforeCutoff返回一个基于某些逻辑的表,其中包含类似 2343 2783 2873

我们将这个 Ids 放入 @orgUsers 表中并作为函数的结果返回。

所以根据要求 -VTN_QualificationMemberLU表有 10 个数据。我们需要通过使用名为 的函数过滤返回 30 个 ID GetStudentsByOUPath_BeforeCutoff。对于每一行,VTN_Qual....我们需要返回 3 个 ID 作为表格结果。

这是要重现的测试脚本。

CREATE TABLE VTN_QualificationMemberLU (
    MemberValue  nvarchar(max) NOT NULL
)


INSERT INTO VTN_QualificationMemberLU (MemberValue) VALUES 
('2385-3772-3764-2918'),
('2385-3772-3764-2918'),
('2382-1237-1203-2367'),
('2123-1238-8123-1232'),
('1238-1222-9982-7129'),
('2385-3772-3764-2918'),
('5645-1232-1203-1232'),
('6675-1238-5655-1232'),
('1238-1233-1232-1231')



CREATE FUNCTION GetStudentsByOUPath_BeforeCutoff  (
    @userIds NVARCHAR(MAX)
)
RETURNS TABLE
AS
RETURN 
    SELECT value  
    FROM STRING_SPLIT(@userIds, '-')  
    WHERE RTRIM(value) <> '';

所以对于VTN_Quali...表的每一行我们需要调用函数并且需要收集函数的表结果。

提前谢谢大家。

4

2 回答 2

0

这是要重现的测试脚本。

我忽略了之前的描述,因为我们不使用 DDL+DML 来重现完整的场景,所以让我们专注于您的示例表和数据

-- DDL+DML
CREATE TABLE VTN_QualificationMemberLU (
    MemberValue  nvarchar(max) NOT NULL
)
GO

INSERT INTO VTN_QualificationMemberLU (MemberValue) VALUES 
('2385-3772-3764-2918'),
('2385-3772-3764-2918'),
('2382-1237-1203-2367'),
('2123-1238-8123-1232'),
('1238-1222-9982-7129'),
('2385-3772-3764-2918'),
('5645-1232-1203-1232'),
('6675-1238-5655-1232'),
('1238-1233-1232-1231')
GO

CREATE FUNCTION GetStudentsByOUPath_BeforeCutoff  (
    @userIds NVARCHAR(MAX)
)
RETURNS TABLE
AS
RETURN 
    SELECT value  
    FROM STRING_SPLIT(@userIds, '-')  
    WHERE RTRIM(value) <> '';
GO

为了对现有表中的所有行执行表的功能,我们可以使用CROSS APPLY

例如:

SELECT t1.MemberValue,t2.[value]
from VTN_QualificationMemberLU t1
CROSS APPLY GetStudentsByOUPath_BeforeCutoff (MemberValue) as t2

显然,如果您只需要函数中的干净值,那么您可以只返回该列t2.[value]

于 2021-09-28T14:42:16.393 回答
-1

好吧,我真的不可能对此进行测试,因为您的问题代码与示例代码和数据之间存在很多差异(缺少变量、列等),但它可能应该是这样的。我刚刚就地注释掉了游标代码,以便您可以更好地了解如何将代码从游标转换为基于集合的代码:

declare @orgusers table (UserID int, PRIMARY KEY (UserID))
delete from @orgusers

--declare curOrgs CURSOR FAST_FORWARD FOR
;WITH cte AS
(   select distinct ('~' + qlu.MemberValue + '~') as curOrgs                    
    FROM [gl].VTN_QualificationMemberLU qlu 
    where qlu.MemberType = 45 and qlu.QualificationID = 1111
)
--open curOrgs
--FETCH NEXT FROM curOrgs INTO @org
--while @@FETCH_STATUS = 0
--begin
    insert into @orgusers(UserID) 
    SELECT distinct u.UserID
    FROM cte AS c
    CROSS APPLY [gl].[GetStudentsByOUPath_BeforeCutoff](@nCompanyid, c.curOrgs, @dCutOffDate) as u
    left join @orgusers ou on ou.UserID = u.UserID
    --where ou.UserID is null
    --fetch next from curOrgs INTO @org
--end 
--close curOrgs
--deallocate curOrgs  

我认为您可能可以摆脱distinctCTE 中的 (您不应该需要两个 DISTINCT,而后一个将完成两者的工作)。

于 2021-09-28T14:43:05.060 回答