将 Case 语句创建为函数

Create Case statement as Function

提问人:Carbine734 提问时间:8/29/2023 最后编辑:marc_sCarbine734 更新时间:8/29/2023 访问量:88

问:

我有一个列中的日期范围表,并分配为第 3 列。PeriodRangesStartDateEndDatePeriod

例如:

开始日期 结束日期 时期
'2023-01-01' '2023-01-28' 1
'2023-01-29' '2023-02-25' 2

然后,我有多个交易表,每个交易表都有一个日期 (entry_date) 数据点。我目前的解决方案是为每个期间创建一个案例陈述,并检查日期是否在这些范围之间并分配期间标签;但是,我的偏好是维护一个日期范围表,并检查日期是否介于 StartDate 和 EndDate 之间并返回相应的时间段,或者创建一个分配周期的函数。

日期“2023-01-05”可能有 10 个条目应全部返回周期 1,然后在日期“2023-02-05”上有 100 个条目应全部返回周期 2,以此类推作为查询的附加列

我尝试修复:

CASE
    WHEN dbo.glentry.Entry_date BETWEEN '2023-01-01' AND '2023-01-28' THEN 'P1'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-01-29' AND '2023-02-25' THEN 'P2'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-02-26' AND '2023-03-25' THEN 'P3'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-03-26' AND '2023-04-22' THEN 'P4'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-04-23' AND '2023-05-20' THEN 'P5'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-05-21' AND '2023-06-17' THEN 'P6'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-06-18' AND '2023-07-15' THEN 'P7'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-07-16' AND '2023-08-12' THEN 'P8'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-08-13' AND '2023-09-09' THEN 'P9'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-09-10' AND '2023-10-07' THEN 'P10'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-10-08' AND '2023-11-04' THEN 'P11'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-11-05' AND '2023-12-02' THEN 'P12'
    WHEN dbo.glentry.Entry_date BETWEEN '2023-12-02' AND '2023-12-31' THEN 'P13'
    ELSE 'Non-2023'
END AS 'Period'

这是我目前的解决方案,但我讨厌在每个查询中插入它。我更希望将其放在表中并使用单个 case 语句或调用函数。

也尝试过这个,但我肯定知道这是不正确的,我不确定如何解决:

CREATE FUNCTION dbo.fn_ConvertDateToPeriod 
    (@Date DATETIME)
RETURNS VARCHAR(20)
AS 
BEGIN
    DECLARE @Period as VARCHAR(20)

    SELECT @Period =
        (CASE
            WHEN @Date BETWEEN dbo.PeriodRanges.[StartDate] AND dbo.PeriodRanges.[EndDate] THEN     dbo.PeriodRanges.[Period]
        END)
    FROM dbo.PeriodRanges

    RETURN @Period
END

我的理想情况是简单地调用查询的 select 语句中的函数,例如:

SELECT
    dbo.fn_ConvertDateToPeriod (dbo.Glentry.Entry_Date),
    etc
    etc
SQL Server 函数 案例

评论

1赞 Squirrel 8/29/2023
为什么不创建一个日历表呢?
4赞 Dale K 8/29/2023
请注意,case 是一个表达式,而不是一个语句。
0赞 devesh 8/29/2023
使用 dateRange Criteria 创建临时表,并根据 StartDate 和 EndDate 将这个新创建的表与目标表联接。这将避免对每次函数调用进行不必要的表扫描。

答:

1赞 eshirvana 8/29/2023 #1

似乎您想用您的:PeriodRanges

select pr.Period , g.*
from dbo.Glentry g 
join dbo.PeriodRanges pr
on g.Entry_Date between pr.[StartDate] AND pr.[EndDate]
0赞 Sam 8/29/2023 #2

正如许多评论所建议的那样,您可以创建一个日期参考表,您可以在其中预先定义您的周期范围。

CREATE TABLE Date_reference(Start_Date date, End_Date date, Period varchar(5));

INSERT INTO Date_reference VALUES
('2023-01-01','2023-01-28','P1'),
('2023-01-29','2023-02-25','P2'),
('2023-02-26','2023-03-25','P3'),
('2023-03-26','2023-04-22','P4');...

然后将此参考表与主表连接起来,以获得所需的输出。

SELECT 
    a.*
    ,b.Period
FROM glentry a
LEFT JOIN Date_reference b
    ON (a.Entry_date >= b.Start_Date) AND (a.Entry_date < b.End_Date)

这样就无需在每次使用函数执行相同操作时扫描列。

评论

3赞 marc_s 8/29/2023
ntext数据类型将在 SQL Server 的未来版本中删除。避免在新的开发工作中使用这些数据类型,并计划修改当前使用它们的应用程序。改用 或。详情请见此处textnvarchar(max)varchar(max)
2赞 Dale K 8/29/2023
对于 2 个字符的字符串,几乎不需要进一步max
0赞 Sam 8/29/2023
谢谢你的建议。我把它作为一个例子发布。尽管如此,还是编辑为使用 varchar
0赞 Amit Mohanty 8/29/2023 #3

下面介绍如何创建函数并在查询中使用它:

CREATE FUNCTION dbo.fn_ConvertDateToPeriod 
    (@Date DATETIME)
RETURNS VARCHAR(20)
AS 
BEGIN
    DECLARE @Period INT

    SELECT @Period = MIN(Period)
    FROM PeriodRanges
    WHERE @Date BETWEEN StartDate AND EndDate

    RETURN CONCAT('P', CAST(@Period AS VARCHAR))
END

现在,您可以在 SELECT 语句中使用此函数:

SELECT
    dbo.fn_ConvertDateToPeriod(dbo.Glentry.Entry_Date) AS 'Period',
    -- Other columns you need
FROM
    dbo.Glentry