【问题标题】:SQL Query to find records that fall between a start and end dateSQL 查询以查找介于开始日期和结束日期之间的记录
【发布时间】:2021-05-10 17:56:21
【问题描述】:

我有一张像下面这样的表,我想获取与 start_date 和 end_date 之间的类相关联的经理

class_id manager_id start_date end_date
1 999 2021-05-05 17:38:48 2021-05-05 17:39:38
2 999 2021-05-05 17:39:38 2021-05-05 17:42:43
3 999 2021-05-05 17:42:43 2021-05-05 17:47:45
4 999 2021-05-05 17:47:45 NULL
CREATE TABLE manager_class
(
   class_id int
   ,manager_id int
   ,start_time timestamp(3)
   ,end_time   timestamp(3)

)

INSERT INTO manager_class VALUES 

(1,999,'2021-05-05 17:38:48'::timestamp(3), '2021-05-05 17:39:38'::timestamp(3))

,(2,999,'2021-05-05 17:39:38'::timestamp(3), '2021-05-05 17:42:43'::timestamp(3))

,(3,999,'2021-05-05 17:42:43'::timestamp(3), '2021-05-05 17:47:45'::timestamp(3))

,(4,999,'2021-05-05 17:47:45'::timestamp(3), NULL)

用例 IF _param_start_date = 2021-05-05 17:30:48 _param_end_date = 2021-05-05 17:42:43 那么结果应该是

class_id start_date end_date
1 2021-05-05 17:38:48 2021-05-05 17:39:38
2 2021-05-05 17:39:38 2021-05-05 17:42:43

如果 _param_start_date = 2021-05-05 17:39:38 _param_end_date = 2021-05-05 17:42:43

class_id start_date end_date
2 2021-05-05 17:39:38 2021-05-05 17:42:43

如果 _param_start_date = 2021-05-05 17:39:38 _param_end_date = 2021-05-05 17:55:43

class_id start_date end_date
2 2021-05-05 17:39:38 2021-05-05 17:42:43
3 2021-05-05 17:42:43 2021-05-05 17:47:45
4 2021-05-05 17:47:45 NULL

IF _param_start_date = '2021-05-05 17:47:45' _param_end_date = '2021-05-05 17:47:46'

class_id start_date end_date
4 2021-05-05 17:47:45 NULL

IF _param_start_date = '2021-05-05 17:39:38' _param_end_date = '2021-05-05 17:47:45'

class_id start_date end_date
2 2021-05-05 17:39:38 2021-05-05 17:42:43
3 2021-05-05 17:42:43 2021-05-05 17:47:45
4 2021-05-05 17:47:45 NULL

IF _param_start_date = '2021-05-05 17:39:38' _param_end_date = '2021-05-05 17:40:00'

class_id start_date end_date
2 2021-05-05 17:39:38 2021-05-05 17:42:43

到目前为止我做了什么:

      SELECT    class_id
            ,mc.start_time
            ,mc.end_time 
    FROM    manager_class AS mc
            
    WHERE   mc.manager_id = 999
            AND ( 
                    (
                        mc.start_time BETWEEN param_start_time AND param_end_time /* replace param_start_time and param_end_time */
                        AND (param_end_time >=   mc.end_time)
                    )
                  
                    OR (
                         param_start_time >= mc.start_time
                         AND (param_end_time <=  mc.end_time OR mc.end_time IS NULL)
                        )   

                )

【问题讨论】:

  • 在您的用例中,您给出了 2 个开始日期。你的意思是开始和结束
  • 如果参数是 start = 2021-05-05 17:39:00, end = 2021-05-05 17:40:00 怎么办?
  • @bwakabats 是的,我的错误是 param_start_date 和 param_end_date
  • @serg for the use_case start = 2021-05-05 17:39:00, end = 2021-05-05 17:40:00 ?结果将是第二条记录 2 2021-05-05 17:39:38 2021-05-05 17:42:43
  • 为什么是第二行而不是第一行? (7:39:00 .. 17:40:00) 也与第一个重叠。

标签: sql postgresql


【解决方案1】:

可以通过这种方式找到重叠间隔。不确定 NULL,此查询认为 mc.end_time is NULL 是无限的间隔。

SELECT   class_id
        ,mc.start_time
        ,mc.end_time 
FROM    manager_class AS mc            
WHERE   mc.manager_id = 999
        AND mc.start_time <= param_end_time  
        AND (mc.end_time is NULL OR param_start_date <= mc.end_time)

【讨论】:

    【解决方案2】:

    如果您的参数或表格列允许包含 null,那么您最好的选择似乎是将每个转换为适当的 range type 并使用 overlaps 运算符。假设所有都定义为timestamps without time zone 那么:

    select class_id
         , mc.start_time
         , mc.end_time 
      from manager_class  mc            
     where mc.manager_id = 999
       and tsrange(parm_start_time, parm_end_time,'[)') &&
           tsrange(mc,start_time,mc.end_time,'[)');   
    

    【讨论】:

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