将存储过程转换为表值函数

问题描述 投票:0回答:1

下面是一个很久以前写的存储过程。是否可以将其转换为表值函数?或者有没有更好的方法或途径可以考虑替代它?

目标是“作为一名报告分析师,我希望能够报告可配置的人口普查点在可配置的天数内的病房停留情况。”

如果我输入 01/01/2023 的

StartDate
(在幕后包含
DateTime
,只是不好的命名)和 01/01/2023 的
EndDate
(相同,实际上是一个日期时间)和下午 2 点的时间生成的数据集将计算这些日期之间的所有活动。

示例

  • 我于 2023 年 1 月 1 日下午 14:01 到达,因此不会被包括在内(我在那里的人口普查日期下午 2 点)
  • 我于 2023 年 1 月 1 日下午 13:59 到达,因此将被包括在内(人口普查日期下午 2 点我尚未到达)

这可能不是特定于某一天的,因此例如我可能想查看一周(7 天)的值,因此如果我在第 1 天再次到达并且一周后仍然在那里,则循环将记录为每天在人口普查时间活跃,例如 01、02、03、04、05、06、07 的@2pm。

最终目标是查看可配置期间内特定时间活跃的所有用户的数据集。

正如我所说,下面的工作当前完成,但所使用的对象不再可以使用我们现在使用的对象进行复制,并且这已经完成,但我问题是否可以使用不同的方法(例如表格)更好地完成这项工作-值函数。

ALTER PROCEDURE [dbo].[HEY_spWardStaysAtCensusDate]
    @StartDate DATE,
    @EndDate DATE,
    @CensusTime TIME
AS
    DECLARE @NoOfDays INT,
            @LoopCounter INT,
            @CensusDate DATETIME

    SELECT 
        @NoOfDays = DATEDIFF(DAY, @StartDate, @EndDate) + 1

    IF OBJECT_ID('tempdb..#WardStays') IS NOT NULL
    BEGIN
        DROP TABLE #WardStays
    END

    CREATE TABLE #WardStays 
    (
        WARD_STAY_UNIQUE_ID INT NOT NULL,
        CENSUS_DATE_TIME DATETIME NOT NULL,
        LOCAL_PATIENT_NUMBER VARCHAR(50) NULL,
        WARD_CODE VARCHAR(50) NULL,
        WARD_START_DATE_TIME DATETIME NULL,
        WARD_END_DATE_TIME DATETIME NULL,
        TRUST_SITE_LOCAL VARCHAR(50) NULL,
        TRUST_SITE_NATIONAL VARCHAR(50) NULL,
        WARD_STAY_COUNTER INT NULL
    )

    SELECT @LoopCounter = 1
  
    WHILE @LoopCounter <= @NoOfDays
    BEGIN
        SET @CensusDate = DATEADD(DAY, @LoopCounter - 1, @StartDate) + CAST(@CensusTime AS DATETIME)

        INSERT INTO #WardStays (WARD_STAY_UNIQUE_ID, CENSUS_DATE_TIME, LOCAL_PATIENT_NUMBER, WARD_CODE, WARD_START_DATE_TIME,
WARD_END_DATE_TIME, TRUST_SITE_LOCAL, TRUST_SITE_NATIONAL, WARD_STAY_COUNTER)
            SELECT 
                IPWardStayID, @CensusDate, HEYNo, WardCode, 
                WardStartDateTime, WardEndDateTime, HospitalCode,
                HospitalNatCode, 1
            FROM 
                HealthBI_Views.dbo.IP_WARD_STAY
            WHERE 
                WardStartDateTime <= @CensusDate
                AND (WardEndDateTime >= @CensusDate OR WardEndDateTime IS NULL)

        SET @LoopCounter = @LoopCounter + 1
    END

    SELECT 
        WARD_STAY_UNIQUE_ID, CENSUS_DATE_TIME, 
        LOCAL_PATIENT_NUMBER, WARD_CODE, 
        WARD_START_DATE_TIME, WARD_END_DATE_TIME, 
        TRUST_SITE_LOCAL, TRUST_SITE_NATIONAL, WARD_STAY_COUNTER
    FROM 
        #WardStays
sql sql-server function tsql stored-procedures
1个回答
0
投票

您可以很容易地转换它。您需要做的就是用对

GENERATE_SERIES
的调用替换循环。在旧版本的 SQL Server 中,您可以使用内联数字函数,例如其中一个

然后计算

datetime
内的
APPLY
值,最后计算
JOIN
主表。

CREATE OR ALTER FUNCTION dbo.HEY_spWardStaysAtCensusDate (
    @StartDate DATE,
    @EndDate DATE,
    @CensusTime TIME
)
RETURNS TABLE
AS RETURN

SELECT 
  WARD_STAY_UNIQUE_ID  = IPWardStayID,
  v.CENSUS_DATE_TIME,
  LOCAL_PATIENT_NUMBER = HEYNo,
  WARD_CODE            = WardCode, 
  WARD_START_DATE_TIME = WardStartDateTime,
  WARD_END_DATE_TIME   = WardEndDateTime,
  TRUST_SITE_LOCAL     = HospitalCode,
  TRUST_SITE_NATIONAL  = HospitalNatCode,
  WARD_STAY_COUNTER    = 1
FROM
    GENERATE_SERIES(0, DATEDIFF(DAY, @StartDate, @EndDate)) g
CROSS APPLY (
    SELECT CENSUS_DATE_TIME =
      DATEADD(day, g.value, @StartDate) + CAST(@CensusTime AS DATETIME)
) v
JOIN
    HealthBI_Views.dbo.IP_WARD_STAY
    ON WardStartDateTime <= v.CENSUS_DATE_TIME 
   AND (WardEndDateTime >= v.CENSUS_DATE_TIME OR WardEndDateTime IS NULL)
;
© www.soinside.com 2019 - 2024. All rights reserved.