在 sql 中使用 udf vs 在性能方面使用 C# 代码中的方法
use udf in sql vs method in C# code in performance
听说是我在 <"SQL"> 验证人员代码分配中的用户定义函数...
每人在一个时间分配卡-没有时间-sheet 节目。 运行 疏散服务时,计时信息发送到此功能以验证人员。
功能return只有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"> 中使用 "user define functions" ?
对于大数据和小数据
你经常使用迭代函数,所以你不能在这种情况下使用内联函数,那么根据这个问题,最好用C#方法处理函数。
根据top Testimonies,我尝试使用内联函数。
然后这个函数由 CTE
:
创建
;WITH PersonnelDetailsByCarnoAndLessTime AS
(
SELECT
PD.*
FROM
tkp_PersonnelDetails PD
JOIN prs_Personnel P ON P.ID = PersonnelBaseId AND P.DELETED = 0 AND P.ACTIVE = 1
JOIN (SELECT PersonnelBaseId,MAX(EffectiveDate) MAX_EffectiveDate
FROM tkp_PersonnelDetails PD
WHERE EffectiveDate <= @Time
GROUP BY PersonnelBaseId
) T ON PD.PersonnelBaseId = T.PersonnelBaseId AND PD.EffectiveDate = T.MAX_EffectiveDate
WHERE PD.Deleted = 0
), R AS
(
SELECT
*
FROM
PersonnelDetailsByCarnoAndLessTime PDL
WHERE CardNo = @Card
), AssignmentCount AS
(
SELECT
MIN(PersonnelBaseId) PersonnelBaseId,
COUNT((CASE WHEN EffectiveDate < @Time THEN 0 ELSE 1 END)) AssignmentCount
FROM
R
)
SELECT CASE WHEN AssignmentCount = 1 THEN PersonnelBaseId ELSE 0 END PersonnelBaseId FROM AssignmentCount
听说是我在 <"SQL"> 验证人员代码分配中的用户定义函数... 每人在一个时间分配卡-没有时间-sheet 节目。 运行 疏散服务时,计时信息发送到此功能以验证人员。 功能return只有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"> 中使用 "user define functions" ? 对于大数据和小数据
你经常使用迭代函数,所以你不能在这种情况下使用内联函数,那么根据这个问题,最好用C#方法处理函数。
根据top Testimonies,我尝试使用内联函数。
然后这个函数由 CTE
:
;WITH PersonnelDetailsByCarnoAndLessTime AS
(
SELECT
PD.*
FROM
tkp_PersonnelDetails PD
JOIN prs_Personnel P ON P.ID = PersonnelBaseId AND P.DELETED = 0 AND P.ACTIVE = 1
JOIN (SELECT PersonnelBaseId,MAX(EffectiveDate) MAX_EffectiveDate
FROM tkp_PersonnelDetails PD
WHERE EffectiveDate <= @Time
GROUP BY PersonnelBaseId
) T ON PD.PersonnelBaseId = T.PersonnelBaseId AND PD.EffectiveDate = T.MAX_EffectiveDate
WHERE PD.Deleted = 0
), R AS
(
SELECT
*
FROM
PersonnelDetailsByCarnoAndLessTime PDL
WHERE CardNo = @Card
), AssignmentCount AS
(
SELECT
MIN(PersonnelBaseId) PersonnelBaseId,
COUNT((CASE WHEN EffectiveDate < @Time THEN 0 ELSE 1 END)) AssignmentCount
FROM
R
)
SELECT CASE WHEN AssignmentCount = 1 THEN PersonnelBaseId ELSE 0 END PersonnelBaseId FROM AssignmentCount