Sql 查询时间范围内基于生效日期的结果

Sql 查询时间范围内基于生效日期的结果,sql,database,oracle,sqlite,date,Sql,Database,Oracle,Sqlite,Date,以下是我尝试为其创建查询的表结构格式: ProductName | Effective_Date |version_number --------------------------------------------- Product1 01-Jan-02 1 Product1 05-Oct-03 2 Product1 03-Mar-04 3 Product1 12-Oct-04

以下是我尝试为其创建查询的表结构格式:

ProductName | Effective_Date |version_number
---------------------------------------------
Product1       01-Jan-02          1
Product1       05-Oct-03          2
Product1       03-Mar-04          3
Product1       12-Oct-04          4
Product1       04-May-05          5
Product1       15-Sep-06          6
Product2       01-Jun-02          1
Product2       03-Sep-08          2
Product3       04-Jun-10          1
Product3       05-Sep-11          2
Product4       16-Jun-03          1
Product4       17-Oct-03          2
Product5       07-Feb-05          1
Product6       01-Jun-02          1
Product6       03-Dec-05          2
Product7       03-Feb-04          1
Product7       05-Nov-10          2
我需要找出在2004-2005年间有效的版本。版本的生效日期确定为:

对于产品1,版本1的有效期为2002年1月1日至2003年10月4日,版本2的有效期为2003年10月5日至2004年3月2日,依此类推

所以版本的有效性是从生效日期到下一个版本创建日期-1

这可能有不同的情况:

  • 没有生效日期在2004-2005年的版本,因此在这种情况下,日期<2004年的最后版本将生效
  • 版本在2004-2005年,如生效日期为2004年3月25日,则应存在有效期至2004年3月24日的版本

  • 请帮助我实现此查询。

    假设您的表名为
    i

    SELECT 
    i.PRODUCTNAME
    , I.VERSION_NUMBER
    , I.EFFECTIVE_DATE START_DATE
    , i2.effective_date end_date  
    from i 
    left join i i2 on i2.version_number = i.version_number +1 and i2.productname = i.productname
    where NOT ((I.EFFECTIVE_DATE <= '01/01/2004' AND nvl(i2.effective_date,sysdate) <= '01/01/2004') OR  (I.EFFECTIVE_DATE >= '12/31/2005' AND nvl(i2.effective_date,sysdate) >= '12/31/2005'))
    
    选择
    i、 产品名称
    ,I.版本号
    ,I.生效日期开始日期
    ,i2.生效日期结束日期
    从我
    在i2.version\u number=i.version\u number+1和i2.productname=i.productname上左键连接i2
    其中不包括((I.生效日期='12/31/2005'))
    
    我创建了
    开始
    结束
    日期,只是使用了下一个版本的
    生效日期
    来匹配产品(假设您不跳过版本,如果跳过,则需要分区/订购)

    有两种情况需要避免。给定的产品/版本在2004年1月1日之前启动和停止,或在2005年12月31日之后启动和停止。要保留的任何其他开始/结束日期组合

    对于没有结束日期的最新版本,我们使用sysdate


    下面的查询将显示2004年1月1日至2005年12月31日期间“生效”的所有版本。它不显示在该时间间隔内没有任何有效版本的产品;如果您需要显示所有的产品,包括这些产品,您将需要一个到“products”表的左外部联接(假设它是一个单独的、较小的联接)


    Oracle还是sqlite?我以为我理解需求,但也许我不理解。您是否需要2004年和2005年期间任何时候处于活动状态的所有版本?或者仅仅是2005年底启用的版本?所有版本均在2014年1月1日至2015年12月31日期间生效。我感谢您的努力。10月17日生效的产品4缺少一行-03@ShekharSharma有道理,这是最新版本,答案更新
    with
         test_data ( ProductName, Effective_Date, version_number ) as (
           select 'Product1', to_date('01-Jan-02', 'dd-Mon-rr'), 1 from dual union all
           select 'Product1', to_date('05-Oct-03', 'dd-Mon-rr'), 2 from dual union all
           select 'Product1', to_date('03-Mar-04', 'dd-Mon-rr'), 3 from dual union all
           select 'Product1', to_date('12-Oct-04', 'dd-Mon-rr'), 4 from dual union all
           select 'Product1', to_date('04-May-05', 'dd-Mon-rr'), 5 from dual union all
           select 'Product1', to_date('15-Sep-06', 'dd-Mon-rr'), 6 from dual union all
           select 'Product2', to_date('01-Jun-02', 'dd-Mon-rr'), 1 from dual union all
           select 'Product2', to_date('03-Sep-08', 'dd-Mon-rr'), 2 from dual union all
           select 'Product3', to_date('04-Jun-10', 'dd-Mon-rr'), 1 from dual union all
           select 'Product3', to_date('05-Sep-11', 'dd-Mon-rr'), 2 from dual union all
           select 'Product4', to_date('16-Jun-03', 'dd-Mon-rr'), 1 from dual union all
           select 'Product4', to_date('17-Oct-03', 'dd-Mon-rr'), 2 from dual union all
           select 'Product5', to_date('07-Feb-05', 'dd-Mon-rr'), 1 from dual union all
           select 'Product6', to_date('01-Jun-02', 'dd-Mon-rr'), 1 from dual union all
           select 'Product6', to_date('03-Dec-05', 'dd-Mon-rr'), 2 from dual union all
           select 'Product7', to_date('03-Feb-04', 'dd-Mon-rr'), 1 from dual union all
           select 'Product7', to_date('05-Nov-10', 'dd-Mon-rr'), 2 from dual
         )
    --  End of test data (NOT part of the SQL query). Query begins BELOW THIS LINE.
    select productname, effective_date, to_date - 1 as to_date, version_number
    from ( select productname, effective_date,
                  lead(effective_date, 1, date '2099-01-01') 
                     over (partition by productname order by effective_date) as to_date,
                  version_number
           from   test_data
         )
    where effective_date <  date '2006-01-01'
      and to_date        >= date '2004-01-01'
    ;
    
    PRODUCTNAME  EFFECTIVE_DATE  TO_DATE         VERSION_NUMBER
    ------------ --------------- --------------- --------------
    Product1     05-Oct-03       02-Mar-04                    2
    Product1     03-Mar-04       11-Oct-04                    3
    Product1     12-Oct-04       03-May-05                    4
    Product1     04-May-05       14-Sep-06                    5
    Product2     01-Jun-02       02-Sep-08                    1
    Product4     17-Oct-03       31-Dec-98                    2
    Product5     07-Feb-05       31-Dec-98                    1
    Product6     01-Jun-02       02-Dec-05                    1
    Product6     03-Dec-05       31-Dec-98                    2
    Product7     03-Feb-04       04-Nov-10                    1
    
    10 rows selected.