【问题标题】:SQL Return a Value depending on 3 ranges of datesSQL 根据 3 个日期范围返回一个值
【发布时间】:2020-04-14 04:37:18
【问题描述】:

我在对 3 个不同日期范围内的某些日期进行排序并根据正确范围返回值时遇到问题。我希望你能给我一个有效和干净的方法。

我从 SQL 表中获得了 6 个不同的日期。然后将这些日期存储在变量中。所有日期也可以是 Null 值。我的日期分为 3 个日期范围。我想通过使用我所有范围中的最早开始日期来返回我所在范围的指示。正确范围的日期也必须小于当前日期。日期范围也可以仅包含结束日期。在这种情况下,我们认为范围在结束日期结束并在此之前处于活动状态。在这种情况下,我们选择最接近当前日期的最早结束日期。

如果所有日期都为空,则返回 0

范围 #1(类别 #1)X 开始日期和 X 结束日期返回 1

范围 #2(类别 #2)Y 开始日期和 Y 结束日期返回 2

范围 #3(类别 #3)Z 开始日期和 Z 结束日期返回 3

编辑

Ex#1 XStart = December 10 , XEnd = December 15  
     YStart = December 12 , Yend = December 13  
     ZStart = December 9 , ZEnd = Null 

Expected result would be Z Category

Ex#2 XStart = December 8 , XEnd = December 15  
     YStart = NULL , Yend = NULL  
     ZStart = December 9 , ZEnd = Null  

Expected result would be X Category

Ex#3XStart = NULL , XEnd = December 15  
   YStart = NULL , Yend = NULL  
 ZStart = December 9 , ZEnd = Null  

Expected result would be X Category

Ex#4 XStart = December 10 , XEnd = December 15  
    YStart = NULL , Yend = NULL  
    ZStart = December 9 , ZEnd = Null  

Expected result would be Z Category

有没有比做很多 IF 语句更有效的方法?我很难处理所有这些条件和检查。这是我目前所拥有的sn-p。

    --Return 0 is not Condition is Applicable

    ALTER PROCEDURE [dbo].[HO_GetReason] 
    @HOID INT   
AS
BEGIN

Declare @IsHOIDReal INT = (SELECT ID from T_HO where id = @HOID)
Declare @XStartDate Datetime 
Declare @XEndDate Datetime 
Declare @YStartDate Datetime 
Declare @YEndDate Datetime 
Declare @ZStartDate Datetime 
Declare @ZEndDate Datetime 

CREATE TABLE #tmpT_HO_Withhold (
    ID INT NOT NULL,
    XStartDate Datetime null,
    XEndDate Datetime null,
    YStartDate Datetime null,
    YEndDate Datetime null,
    ZStartDate Datetime null,
    ZEndDate Datetime null,
    PRIMARY KEY CLUSTERED (ID)
)

IF (@IsHOIDReal IS NOT NULL) 
BEGIN
    INSERT INTO #tmpT_HO_Withhold
    SELECT T_HO.ID, 
    XStartDate ,
    XEndDate ,
    YStartDate ,
    YEndDate ,
    ZStartDate ,
    ZEndDate
    FROM dbo.T_HO
    WHERE ID = @HOID

    SET @XStartDate = (Select TOP 1 XStartDate from #tmpT_HO_Withhold)
    SET @XEndDate = (Select TOP 1 XEndDate from #tmpT_HO_Withhold)
    SET @YStartDate = (Select TOP 1 YStartDate from #tmpT_HO_Withhold)
    SET @YEndDate = (Select TOP 1 YEndDate from #tmpT_HO_Withhold)
    SET @ZStartDate = (Select TOP 1 ZStartDate from #tmpT_HO_Withhold)
    SET @ZEndDate = (Select TOP 1 ZEndDate from #tmpT_HO_Withhold)

    IF(@XStartDate IS NULL AND @YStartDate IS NULL AND @ZStartDate IS NULL)
    BEGIN  print 'NO CONDITION' Select 0 as 'HO_GetReason'  END

    ELSE IF (@XStartDate IS NOT NULL AND @YStartDate IS NULL AND @ZStartDate IS NULL) BEGIN print '1' Select 1 as 'HO_GetReason'END

    ELSE IF (@XStartDate IS NOT NULL AND @YStartDate IS NULL AND @ZStartDate IS NULL) BEGIN print '2' Select 2 as 'HO_GetReason'END

    ELSE IF (@XStartDate IS NULL AND @YStartDate IS NULL AND @ZStartDate IS NOT NULL) BEGIN print '3' Select 3 as 'HO_GetReason'END

END
DROP TABLE #tmpT_HO_Withhold END

【问题讨论】:

  • 样本数据和预期结果会有所帮助。他们应该澄清“使用我所有范围内的最早开始日期”与依次检查 X、Y、Z 日期并使用第一个匹配作为结果而不比较开始日期之间的混淆。并且“必须也小于当前日期”而不与当前日期进行任何比较?如果多个开始日期为空(或将来),那么您如何选择结果,例如最早的结束日期 >= 今天?
  • 我用一些我正在尝试做的例子来解决我的问题。请看一看。

标签: tsql sorting date validation datetime


【解决方案1】:

关于高效清洁的注意事项:

复杂条件不属于低效类别。它可能属于难以阅读和维护的类别,但它们的操作非常快捷。

  • 示例:第二个“else if”与第一个“else if”奇怪地相似。将无法访问代码。

创建和销毁临时表将是存储过程中最慢的部分。

  • 使用 #tablename 的临时表在存储过程中不是并发安全的,在某些情况下您可能会遇到奇怪的架构更改错误。

您可以通过将大部分内容与以下内容交换来获得相同的结果:

SELECT 
    @XStartDate = XStartDate ,
    @XEndDate = XEndDate ,
    @YStartDate = YStartDate ,
    @YEndDate = YEndDate ,
    @ZStartDate = ZStartDate ,
    @ZEndDate = ZEndDate
FROM dbo.T_HO
WHERE ID = @HOID

根据您创建表中发现的主键,ID 是唯一的,因此这种格式不需要 TOP,任何行都不会将值保留为空。


就我个人而言,一旦我得到条件工作(绝对最终形式),我会很想直接将其调整为 CASE 语句并将其设置为基表中的 PERSISTENT 计算 COLUMN。

ALTER TABLE dbo.T_HO ADD Reason AS (CASE WHEN XStartDate IS NOT NULL AND ... THEN ... WHEN ... THEN ... ELSE 0 END) PERSISTED

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多