【发布时间】:2019-11-23 11:04:51
【问题描述】:
听到的是我在验证代码中的用户定义函数人员代码分配... 时间分配中的每个人员在时间表程序中的卡号。运行疏散服务时,计时员信息发送到此功能以验证人员。 功能在只有 1 个人员分配到此卡时返回有效人员。
ALTER FUNCTION [dbo].[GetPerosnnleBaseIdByCardAndTime]( @Card VARCHAR(100),@Time SMALLDATETIME)
RETURNS INT
AS
BEGIN
----------------
--DECLARE @Card VARCHAR(100) = '11000'
--DECLARE @Time SMALLDATETIME = '2019-02-01 00:00:00'--GETDATE()
---------------------------------
DECLARE @MaxDate SMALLDATETIME
DECLARE @PersonnelBaseId INT
DECLARE @Current int = 0
SELECT
@MaxDate = MAX(EffectiveDate)
FROM
dbo.tkp_PersonnelDetails records
inner join prs_Personnel personnel on personnel.Id = records.PersonnelBaseID AND
Personnel.Active = 1 AND
Personnel.Deleted = 0 AND
records.Deleted = 0
WHERE records.Deleted = 0 AND records.EffectiveDate <= @Time AND CardNo = @Card
SELECT @PersonnelBaseId = PersonnelBaseId, @Current = [Current] FROM dbo.tkp_PersonnelDetails WHERE EffectiveDate = @MaxDate AND Deleted = 0 AND CardNo = @Card
IF ((SELECT COUNT(*) FROM dbo.tkp_PersonnelDetails WHERE CardNo = @Card AND EffectiveDate <= @Time AND Deleted = 0) = 1)
RETURN @PersonnelBaseId
--IF @Current = 1
-- SELECT @PersonnelBaseId
---------
DECLARE @DETAILS TABLE (PersonnelBaseId INT,CardNo VARCHAR(100),EffectiveDate SMALLDATETIME,ROW_NO INT,PERS_NNUMBER INT)
INSERT INTO @DETAILS
SELECT
PD.PersonnelBaseId,CardNo,EffectiveDate
,ROW_NUMBER() OVER(PARTITION BY PD.PERSONNELBASEID ORDER BY EFFECTIVEDATE) AS ROW_NO
,DENSE_RANK() over(ORDER BY PD.PERSONNELBASEID) AS PERS_NNUMBER
FROM
dbo.tkp_PersonnelDetails PD
WHERE PersonnelBaseId in (select PersonnelBaseId from dbo.tkp_PersonnelDetails where CardNo = @Card)
ORDER BY
PERS_NNUMBER,ROW_NO
DECLARE @CurrectPersonnelCount int = 0
DECLARE @MaxPersNumber int = 1,@MaxRowNumber int = 1
DECLARE @PersNumber int = 1,@RowNumber int = 1
DECLARE @_PersonnelBaseId int ,@_CardNo varchar(100) ,@_EffectiveDate smalldatetime,@_CardNoNext varchar(100) ,@_EffectiveDateNext smalldatetime
SELECT @MaxPersNumber = max(PERS_NNUMBER) FROM @DETAILS
WHILE @PersNumber <= @MaxPersNumber
BEGIN
SELECT @_PersonnelBaseId = PersonnelBaseId,@_CardNo = CardNo,@_EffectiveDate = EffectiveDate FROM @DETAILS WHERE PERS_NNUMBER = @PersNumber AND ROW_NO = @RowNumber
SELECT @MaxRowNumber = max(ROW_NO) FROM @DETAILS WHERE PersonnelBaseId = @_PersonnelBaseId
WHILE @RowNumber <= @MaxRowNumber
BEGIN
IF @_CardNo = @Card and @_EffectiveDate <= @Time
BEGIN
SELECT @_CardNoNext = CardNo,@_EffectiveDateNext = EffectiveDate FROM @DETAILS WHERE PERS_NNUMBER = @PersNumber AND ROW_NO = @RowNumber +1
IF @_EffectiveDateNext > @Time OR @_EffectiveDateNext IS NULL
BEGIN
SET @CurrectPersonnelCount += 1
SET @PersonnelBaseId = @_PersonnelBaseId
END
END
SET @RowNumber += 1
SELECT @_PersonnelBaseId = PersonnelBaseId,@_CardNo = CardNo,@_EffectiveDate = EffectiveDate FROM @DETAILS WHERE PERS_NNUMBER = @PersNumber AND ROW_NO = @RowNumber
END
SET @PersNumber += 1
END
IF @CurrectPersonnelCount = 1
RETURN @PersonnelBaseId
ELSE
RETURN 0
--SELECT * FROM @DETAILS
RETURN 0
END
我可以用 C# 编写这个函数,但想知道哪个是最佳实践? 在 C# 方法或 中的“用户定义函数”中使用? 适用于大数据和小数据
【问题讨论】:
-
如果您要在 SQL Server 中使用用户定义的函数,请使用内联表值函数;众所周知,标量和多行表值函数都表现不佳。但是,如果您使用的是 SQL Server 2019,则可以利用内联标量函数功能。
-
为什么不在单独的表中使用映射 Personnel-Card-no?
-
另外,
WHILE循环对于任何 SQL 来说都是一个非常糟糕的主意。除非您真的需要迭代任务(其中很少有场景)。您真的想使用基于集合的方法。 -
@Larnu 你的意思是如果我使用 SQL Server 2019 那么它不是在 .net 中吗?而且这个问题不依赖于数据规模?
-
那不是我说的@abbasezoji,不。我说如果您使用 SQL Server,而不是“使用 SQL Server 2019”(仍处于预览阶段)。无论如何,您将无法将上述内容转换为内联标量函数。
标签: c# sql-server bigdata performance-testing