3

我在SQLFiddle中定义了下表和行

我需要从产品表中选择两行之间的差异start_datenvl(return_date,end_date)1 的行。即start_date当前行和nvl(return_date,end_date)前一行应该是一个

例如

PRODUCT_NO TSH098and PRODUCT_REG_NO FLDG, theEND_DATEAugust, 15 2012PRODUCT_NO TSH128andPRODUCT_REG_NO FLDG start_dateAugust, 16 2012,所以差别只有一天。

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

任何帮助都是非常可观的。

谢谢

4

5 回答 5

2

在 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))

SQL Fiddle 上的实时示例。

于 2012-09-16T08:27:48.837 回答
2

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

select *
  from products p
  join (select *
         from(select p.Product_no
                   , p.Product_Reg_No
                   , case 
                       when (lag(start_date, 1, start_date) over(order by product_reg_no)-
                            nvl(return_date, end_date)) = 1 
                            then lag(start_date, 1, start_date) 
                                   over(order by product_reg_no) 
                        end start_date
                   , End_Date
                   , Return_Date
               from products p 
              order by 2,1 desc
              )
        where start_date is not null
       ) s
    on (p.start_date = s.start_date or p.end_date = s.end_date)
 order by 2, 1 desc

SQL Fiddle 演示

于 2012-09-16T10:23:47.180 回答
2

将当前行与前一行进行比较的方法是使用 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 查询您的表两次,根据日期进行过滤。结果集中的每一行都包含来自每个表的记录。如果给定的 start_date 与多个 end_date 匹配,反之亦然,您将获得多次点击的记录。

于 2012-09-16T10:43:21.490 回答
2

我的印象是,如果产品注册不匹配,您只希望匹配日期相差 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)

SQL小提琴

如果我对分组有误,那么只需离开连接条件,这与给定的示例产品表带来相同的结果

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)

SQL 小提琴 2

现在你说差异是 1 天。我自动假设 start_date 比 nvl(return_date,end_date) 高 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))

SQL 小提琴 3

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

编辑:根据您的评论,您希望比较 return_date orend_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)

SQL 小提琴 4

于 2012-09-16T11:43:02.383 回答
2

你的意思是这样吗?

SELECT T2.*
FROM PRODUCTS T1
    JOIN PRODUCTS T2 ON (
        nvl(T1.end_date, T1.return_date) + 1 = T2.start_date
    );

您的 SQL Fiddle 示例中,它返回:

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,因为 TSH116end_date是 2012 年 8 月 7 日。
  • 返回 TSH137,因为 TSH125end_date是 2012 年 9 月 7 日。

如果您只想比较相同的行product_reg_no,很容易将其添加到 JOIN 条件中。如果您想要 1 天差异的两个“方向”,也很容易添加它。

于 2012-09-16T14:06:41.827 回答