Sql 获取日期差为1的行

Sql 获取日期差为1的行,sql,database,oracle,oracle10g,date-arithmetic,Sql,Database,Oracle,Oracle10g,Date Arithmetic,我在中定义了下表和行 我需要从products表中选择两行之间的差异start\u date和 nvl(返回日期、结束日期)为1。i、 e.当前行的start\u date和前一行的nvl(返回日期、结束日期)应为一 比如说 产品编号TSH098和产品编号FLDG,结束日期为2012年8月15日和 产品编号TSH128和产品编号FLDG开始日期为2012年8月16日,因此差异仅为一天 如何使用sql获得所需的输出 任何帮助都是值得赞赏的 谢谢在SQL中,date+X为日期添加X天。因此,您可以:

我在中定义了下表和行

我需要从products表中选择两行之间的差异
start\u date
nvl(返回日期、结束日期)
为1。i、 e.当前行的
start\u date
和前一行的
nvl(返回日期、结束日期)
应为一

比如说

产品编号TSH098
产品编号FLDG
结束日期为2012年8月15日
产品编号TSH128
产品编号FLDG
开始日期
2012年8月16日,因此差异仅为一天

如何使用sql获得所需的输出

任何帮助都是值得赞赏的


谢谢

在SQL中,
date+X
为日期添加X天。因此,您可以:

select  * 
from    products
where   start_date + 1 = nvl(end_date, return_date)
如果日期可能包含时间部分,请使用
trunc
删除时间部分:

select  * 
from    products
where   trunc(start_date) + 1 = trunc(nvl(end_date, return_date))

您可以使用分析功能访问当前位置之前给定物理偏移处的行。根据您的排序顺序,它可能看起来像这样(虽然不是那么优雅)


比较当前行和前一行的方法是使用LAG()函数。大概是这样的:

select * from 
(
select p.* 
       , lag (end_date) over 
         (order by start_date )
         as prev_end_date
       , lag (return_date) over 
         (order by start_date )
         as prev_return_date
from products p
)
where (trunc(start_date) - 1) = trunc(nvl(prev_return_date, prev_end_date))
order by 2,1 desc
但是,这不会返回所需的结果,因为您尚未定义用于定义排序顺序的机制。如果没有排序顺序,“前一行”的概念就没有意义

但是,您可以做的是:

select p1.* 
       , p2.*
from products p1 cross join products p2
where (trunc(p2.start_date) - 1) = trunc(nvl(p1.return_date, p1.end_date))
order by 2, 1 desc

此SQL查询表两次,根据日期进行过滤。结果集中的每一行包含每个表中的一条记录。如果给定的开始日期与多个结束日期匹配,或者反之亦然,您将获得多次点击的记录

我的印象是,如果产品注册不匹配,您只希望匹配日期相差1天。所以我只是简单地把它连接起来,我想这就是你想要的

select p1.product_reg_no,
       p1.product_no product_no_1,
       p2.product_no product_no_2,
       p1.start_date start_date_1,
       nvl(p2.return_date,p2.end_date) return_or_end_date_2
  from products p1
  join products p2 on (p1.product_reg_no = p2.product_reg_no)
where  p1.start_date-1 = nvl(p2.return_date,p2.end_date)

如果我在分组上有错误,那么只需离开连接条件,它与给定的示例products表产生相同的结果

select p1.product_reg_no,
       p1.product_no product_no_1,
       p2.product_no product_no_2,
       p1.start_date start_date_1,
       nvl(p2.return_date,p2.end_date) return_or_end_date_2
  from products p1, products p2
where  p1.start_date-1 = nvl(p2.return_date,p2.end_date)

现在你说差别是1天。我自动假设开始日期比nvl(返回日期、结束日期)高1天。我还假设日期总是午夜。但要将所有这些都排除在外,您可以使用trunc并朝两个方向前进:

select p1.product_reg_no,
       p1.product_no product_no_1,
       p2.product_no product_no_2,
       p1.start_date start_date_1,
       nvl(p2.return_date,p2.end_date) return_or_end_date_2
  from products p1, products p2
where  trunc(p1.start_date)-1 = trunc(nvl(p2.return_date,p2.end_date))
    or trunc(p1.start_date)+1 = trunc(nvl(p2.return_date,p2.end_date))

这一切都是有效的,因为日期(不是时间戳)可以通过加和减来计算

编辑:在您的评论之后,您希望比较返回日期
或结束日期,并且还需要相同的日期:

select p1.product_reg_no,
       p1.product_no product_no_1,
       p2.product_no product_no_2,
       p1.start_date start_date_1,
       p2.return_date return_date_2,
       p2.end_date end_date_2
  from products p1, products p2
where  trunc(p1.start_date)   = trunc(p2.return_date)
    or trunc(p1.start_date)-1 = trunc(p2.return_date)
    or trunc(p1.start_date)+1 = trunc(p2.return_date)
    or trunc(p1.start_date)   = trunc(p2.end_date)
    or trunc(p1.start_date)-1 = trunc(p2.end_date)
    or trunc(p1.start_date)+1 = trunc(p2.end_date)
你是说像这样

SELECT T2.*
FROM PRODUCTS T1
    JOIN PRODUCTS T2 ON (
        nvl(T1.end_date, T1.return_date) + 1 = T2.start_date
    );
在中,它返回:

PRODUCT_NO    PRODUCT_REG_NO    START_DATE                          END_DATE                            RETURN_DATE
TSH128        FLDG              August, 16 2012 00:00:00-0400       September, 15 2012 00:00:00-0400    (null)
TSH125        SCRW              August, 08 2012 00:00:00-0400       September, 07 2012 00:00:00-0400    (null)
TSH137        SCRW              September, 08 2012 00:00:00-0400    October, 07 2012 00:00:00-0400      (null)
  • 返回TSH128的原因您已经解释过了
  • 返回TSH125是因为TSH116的结束日期是2012年8月7日
  • 返回TSH137是因为TSH125的结束日期是2012年9月7日

如果只想比较同一
产品\u reg\u no
中的行,可以很容易地将其添加到联接条件中。如果您想要1天差异的两个“方向”,也很容易添加。

我要查找的是
start\u date
nvl(return\u date,end\u date)
的差异为1的行。i、 例如,当前行的
start\u date
和前一行的
nvl(返回日期,结束日期)
应为一个,例如,产品编号为TSH098的产品注册号FLDG
start\u date
和产品编号TSH128
nvl(返回日期,结束日期)
为一个。我希望我的解释正确。啊哈,我错过了“前一排”部分。我得走了,但是看看谢谢你的解决方案。对于
产品注册号
产品编号TSH098
TSH12
具有
开始日期
nvl(返回日期,结束日期)
一个差值,但未选择该差值。我想选择所有日期差为1的记录。Nicholas非常感谢,因为这看起来不错,我正在测试我的结果。我有一个小疑问,即在哪里包括我的where条件,如
where PRODUCT\u REG\u NO='FLDG'
?它应该在
开始\u日期不为空的位置之后
或者正好在
上一个订单的上方2,1 desc
Regard如果您想筛选最终结果,则可能正好在上一个订单的上方。我正在测试结果,请检查以下内容,我没有在as
select*from products p
有记录的地方执行任何结果,这都是关于排序顺序的。在您的问题中,您一直按产品编号和产品编号进行排序。在您给我的上一个示例中,您是按开始日期(3)进行排序的(以下是一个示例)。您只需决定要使用哪些列对数据进行排序不确定为什么要执行
交叉联接
?外部行没有任何线索。不足以执行
内部连接
例如:
从p1连接p2 ON(trunc(p2.start\u date)-1)=trunc(nvl(p1.return\u date,p1.end\u date))
?@WojtusJ-两个解决方案返回相同的结果。我更喜欢交叉连接,因为它能更好地传达意图;在我看来,内在的结合意味着一种关键的关系。但你的品味或理解可能会有所不同。我明白了,这其实是有道理的。:-)@WojtusJ-也许WITH子句混淆了这个问题:它们是早期解决它的尝试的遗迹,我应该完全重构它们(我现在已经完成了)。感谢您的帮助。我面临的一个主要问题是这个。对于
产品注册号
产品编号TSH098
TSH12
具有
开始日期
nvl(返回日期,结束日期)
一个差值,但未选择该差值。我想选择所有日期差为1的记录。我该怎么做?关于TSH098,其返回日期为2012年5月31日<代码>TSH012
的开始日期为2012年6月18日。因此,条件不匹配<代码>NVLsa
PRODUCT_NO    PRODUCT_REG_NO    START_DATE                          END_DATE                            RETURN_DATE
TSH128        FLDG              August, 16 2012 00:00:00-0400       September, 15 2012 00:00:00-0400    (null)
TSH125        SCRW              August, 08 2012 00:00:00-0400       September, 07 2012 00:00:00-0400    (null)
TSH137        SCRW              September, 08 2012 00:00:00-0400    October, 07 2012 00:00:00-0400      (null)