oracle sql 匹配 一位,关于在SQL中查找匹配间隔:在SQL中查找匹配间隔-Oracle

本文介绍了如何在Oracle SQL中通过JOIN操作找出表2中的时间区间(如15-12-09到31-12-09)在表1(包含2009-2010年每月、季度和年度数据)中的对应时间范围。作者提供了SUBINTERVAL和INTERSECT两种匹配策略,并给出了具体的SQL查询脚本和示例数据。
摘要由CSDN通过智能技术生成

我有一张桌子:

表:

START         END

1 Jan 09    31 Jan 2009

1 Feb 09    28 Feb 2009

1 Mar 09    31 Mar 2009

1 Apr 09    01 May 2009

1 May 09    31 May 2009

1 Jun 09    01 Jul 2009

1 Jul 09    31 Jul 2009

1 Aug 09    31 Aug 2009

1 Sep 09    01 Oct 2009

1 Oct 09    31 Oct 2009

1 Nov 09    01 DEC 2009

1 DEC 09    31 DEC 2009

1 Jan 10    31 Jan 2010

1 Feb 10    03 Mar 2010

1 Mar 10    31 Mar 2010

1 Apr 10    01 May 2010

1 May 10    31 May 2010

1 Jun 10    01 Jul 2010

1 Jul 10    31 Jul 2010

1 Aug 10    31 Aug 2010

1 Sep 10    01 Oct 2010

1 Oct 10    31 Oct 2010

1 Nov 10    01 DEC 2010

1 DEC 10    31 DEC 2010

1 Jan 09    31 Mar 2009

1 Apr 09    30 Jun 2009

1 Jul 09    01 Oct 2009

1 Oct 09    31 DEC 2009

1 Jan 10    31 Mar 2010

1 Apr 10    30 Jun 2010

1 Jul 10    01 Oct 2010

1 Oct 10    31 DEC 2010

1 Jan 09    31 DEC 2009

1 Jan 10    31 DEC 2010

以上包含2009年,2010年的每个月,每个季度和每年。

我有另一个带有以下内容的表:

表2

START       END

15-12-09    31-12-09

15-01-12    31-12-13

01-01-11    31-12-13

30-01-98    31-12-13

01-01-98    31-12-13

01-01-98    31-12-13

23-12-12    31-12-13

12-11-11    31-12-13

01-01-10    31-12-13

对于表2中的每个条目,我需要找到它可能落入表1中的时间范围。

对于前。 从表2,第一个条目开始-

15-12-09    31-12-09

属于:

1 DEC 09    31 DEC 2009

1 Oct 09    31 DEC 2009

1 Jan 09    31 DEC 2009

在Oracle SQL中是否可以识别它?

如果可能的话,您可以提供插入脚本吗?

返回一个表中的结束日期在另一表中的开始日期之后或等于开始日期,并且该表中的开始日期在另一表的结束日期之前或之后的记录。

Marmite Bombers的答案为这两种情况都提供了正确的答案...

您必须先定义table1间隔下降的含义

一般有两种可能的解释。 SUBINTERVAL比较严格,

即匹配间隔完全被参考间隔覆盖。

MATCH              

reference    

另一种更为宽松的可能性是"相交",这意味着两个间隔至少有一个共同点。

MATCH                      

reference  

根据该决定,您使用不同的联接条件。

在下面第一种可能性的查询中,只需交换注释即可获得另一个选项。

请注意,下面将创建带有模拟数据的表。

SELECT

tab2.start_d match_start, tab2.end_d match_end,

tab.start_d ref_start, tab.end_d ref_end

FROM tab2

JOIN tab

-- option SUBINTERVAL

ON tab.start_d <= tab2.start_d AND tab2.end_d <= tab.end_d

-- option INTERSEC

--  on NOT (tab2.end_d <  tab.start_d OR tab2.start_d > tab.end_d)

ORDER BY 1,2,3;

SUBINTERVAL选项的结果

MATCH_START       MATCH_END         REF_START         REF_END

----------------- ----------------- ----------------- -----------------

15.12.09 00:00:00 31.12.09 00:00:00 01.01.09 00:00:00 31.12.09 00:00:00

15.12.09 00:00:00 31.12.09 00:00:00 01.10.09 00:00:00 31.12.09 00:00:00

15.12.09 00:00:00 31.12.09 00:00:00 01.12.09 00:00:00 31.12.09 00:00:00

您将获得更多关于INTERSECT选项的记录。

这是测试数据

CREATE TABLE tab AS

WITH tab AS (

-- reference intervals

-- months

SELECT add_months(to_date('01012009','ddmmyyyy'),rownum-1) start_d,

add_months(to_date('01012009','ddmmyyyy'),rownum)-1 end_d FROM dual CONNECT BY level <=24

UNION ALL

-- quartals

SELECT add_months(to_date('01012009','ddmmyyyy'),3*(rownum-1)) start_d,

add_months(to_date('01012009','ddmmyyyy'),3*rownum)-1 end_d FROM dual CONNECT BY level <=24/3

UNION ALL

-- years

SELECT add_months(to_date('01012009','ddmmyyyy'),12*(rownum-1)) start_d,

add_months(to_date('01012009','ddmmyyyy'),12*rownum)-1 end_d FROM dual CONNECT BY level <=24/12

)

SELECT * FROM tab;

CREATE TABLE tab2 AS

WITH tab2 AS (

-- matched intervals

SELECT to_date('15-12-09','dd-mm-rr') start_d,     to_date('31-12-09','dd-mm-rr') end_d FROM dual UNION ALL

SELECT to_date('15-01-12','dd-mm-rr') start_d,     to_date('31-12-13','dd-mm-rr') end_d FROM dual UNION ALL

SELECT to_date('15-01-98','dd-mm-rr') start_d,     to_date('31-12-13','dd-mm-rr') end_d FROM dual

)

SELECT * FROM tab2;

如果我在tab2中将15-01-12更改为15-01-98,它将失败。

@当什么失败? tab的任何间隔都不包括15-01-98到31-12-13的间隔,那里的查询在START和END列中返回NULL。 我将此新行添加到tab2

如果我更改从双TO中选择to_date(15-01-12,dd-mm-rr)start_d,to_date(31-12-13,dd-mm-rr)end_d选择to_date(15-01-98,dd-mm -rr)start_d,to_date(31-12-13,dd-mm-rr)end_d来自对偶,它为我提供了NULL

@dang-您期望获得什么其他价值? 对于表2中的每个条目,我需要找到它可能落在表1中的时间范围。您是说它与表1相交吗? 即 在这种情况下,来自table1的所有记录?

最终查询是什么?

简单之间应该有所帮助。

使用两个之间的语句首先检查table1的时间范围内是否为table2的start_date,第二个之间的语句将检查table1的相同时间范围内是否也为table2的end_date。两项检查应同时进行,因此应在它们之间使用和。

此外,成为包含在内的"之间"的工作方式如下:对于第一个参数

它检查>或=以及第二个参数

因此,以下语句等于:

t2.start_date BETWEEN t1.start_date AND t1.end_date

t2.start_date >= t1.start_date AND t2.start_date <= t1.end_date

您要查找的SQL将如下所示:

SELECT t2.*, '->', t1.* FROM table2 t2,

table1 t1

WHERE t2.start_date BETWEEN t1.start_date AND t1.end_date

AND t2.end_date BETWEEN t1.start_date AND t1.end_date

我没有很出色的表现就选择了不是很简单的方法=)

WITH days (dt, max_dt) AS

(SELECT (SELECT MIN(start_dt) FROM table2) AS dt

,(SELECT MAX(end_dt) FROM table2) AS max_dt

FROM dual

UNION ALL

SELECT dt+1 AS dt

,max_dt AS max_dt

FROM days

WHERE dt

)

SELECT DISTINCT

t2.start_dt AS start_dt2

,t2.end_dt AS end_dt2

,t.start_dt AS start_dt

,t.end_dt AS end_dt

FROM table2 t2

JOIN days d ON (t2.start_dt <=d.dt AND t2.end_dt >= d.dt)

JOIN TABLE t ON (t.start_dt <=d.dt AND t.end_dt >= d.dt)

我尝试介绍以下情况:

TABLE INTERVAL        |---------|

table2 INTERVAL    |---------------|

table2 INTERVAL         |----|

table2 INTERVAL             |--------|

table2 INTERVAL    |-----|

在SQL中,表达间隔的最佳方式是:

SELECT *

FROM table2

JOIN table1

ON

table1.start BETWEEN table2.start AND table2.end

OR

table2.start BETWEEN table1.start AND table1.end;

每个相交的情况都属于这两种情况之一。

首先,如果您将所有内容都以标准DATE格式存储,那么生活将变得非常简单,这样您就无需在查询中进行转换。那么模式就是:

WHERE table2.start <= table1.end

AND table1.start <= table2.end

我真的不了解您的意思以及您想在这里实现的目标,但是我希望这会对您有所帮助。不知何故,我能够(部分地)获得您所引用的输出。只需对此代码进行一些调整即可。

SELECT  CONVERT(VARCHAR(25),CONVERT(DATE,tbl1.START)) 'start',

CONVERT(VARCHAR(25),CONVERT(DATE,tbl1.[END])) 'end',

CONVERT(VARCHAR(25),CONVERT(DATE,tbl2.START)) + ' - ' + CONVERT(VARCHAR(25),CONVERT(DATE,tbl2.[END])) 'table2'

从tbl1,tbl2

其中(CONVERT(DATE,tbl2.START)> = CONVERT(DATE,tbl1.START))和

(CONVERT(DATE,tbl1。[END])<= CONVERT(DATE,tbl1。[END]))

嗯 这似乎不像Oracle语法。 您认为CONVERT()函数有什么作用?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值