【问题标题】:Oracle SQL comparing two columns in a for loopOracle SQL比较for循环中的两列
【发布时间】:2015-07-28 13:02:48
【问题描述】:

我正在尝试根据两个日期比较 SQL 表中的两列。该表已设置,因此表 A 中的每个人都有另一个表 B 的外键,每个人在表 B 中可以有多个条目。表 B 中的每个条目都包含一个开始日期和结束日期,我试图抓住每个在表 B 中有重叠的人,因此其中一个条目的开始日期在任何其他条目的结束日期之前。

所以表 A 中的 John Doe 在表 B 中有两个条目,其中条目 1 的开始日期是 2015 年 4 月 5 日,结束日期是 2016 年 4 月 6 日,第二个条目是 2016 年 1 月 10 日,结束日期是 2017 年 1 月 10 日,所以我会想要将此人包含在我的结果集中。

但是,表 A 中的 Jane Doe 作为表 B 中的两个条目

Entry 1: SD April 10th 2014 End April 10th 2015
Entry 2: SD May 11th 2015 End May 11th 2016

所以我不想将 Jane Doe 包含在我的结果集中。

我想我需要在 select 语句的 where 部分使用两个嵌套的 for 循环,根据我是否要包含此人来回翻转变量。

类似的东西

Select * from A 
where 
(reset variable
for b in
(select * from b.id = A.b_id); loop
    for btwo in 
    (select * from b.id = A.b_id); loop
    // set variable based on start / end date
    // if I want to include set var = 1 else 0
    end loop;
end loop;)
variable = 1;

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    您已针对两个数据库系统标记了此问题 - 我的回答与 Oracle 相关。

    此处无需使用循环,您可以使用 SQL 分析函数 LAG 来处理此类问题。

    以下将提供您正在寻找的结果:

    SELECT DISTINCT T.NAME
      FROM (SELECT A.NAME,
                   B.START_DATE,
                   B.END_DATE,
                   LAG(B.START_DATE) OVER (PARTITION BY A.NAME ORDER BY B.NAME, B.START_DATE) AS PREV_START,
                   LAG(B.END_DATE) OVER (PARTITION BY A.NAME ORDER BY B.NAME, B.START_DATE) AS PREV_END
              FROM A
              INNER JOIN B
                ON B.NAME = A.NAME
              ORDER BY A.NAME) T
      WHERE (T.START_DATE BETWEEN T.PREV_START AND T.PREV_END) OR
            (T.END_DATE BETWEEN T.PREV_START AND T.PREV_END) OR
            (T.PREV_START BETWEEN T.START_DATE AND T.END_DATE) OR
            (T.PREV_END BETWEEN T.START_DATE AND T.END_DATE);
    

    SQLFiddle here

    【讨论】:

      【解决方案2】:

      这是我的建议。要获得重叠,您可以使用:

      select b.*
      from tableb b
      where exists (select 1
                    from tableb b2
                    where b.aid = b2.aid and
                          b.startdate < b2.enddate and b.enddate > b.startdate
                   );
      

      逻辑很简单。如果第一个在第二个结束之前开始,而第一个在第二个开始之后结束,则两个时间跨度重叠。

      要获取表格的值:

      with overlaps as (
            select b.*
            from tableb b
            where exists (select 1
                          from tableb b2
                          where b.aid = b2.aid and
                                b.startdate < b2.enddate and b.enddate > b.startdate
                         )
          )
      select a.*
      from tablea a
      where a.aid in (select o.aid from overlaps o);
      

      注意:根据您定义“重叠”的方式,您可能需要&lt;=&gt;= 进行比较。

      【讨论】:

      • 非常感谢! :D :D
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 2020-02-16
      • 2020-08-19
      相关资源
      最近更新 更多