Sql 带开始和结束日期的组价格

Sql 带开始和结束日期的组价格,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,我有一张桌子 Recordid Price Start date end date ----------------------------------------- 1 20 2017-10-01 2017-10-02 2 20 2017-10-03 2017-10-04 3 30 2017-10-05 2017-10-05 4 20 2017-10-06 2017-10-

我有一张桌子

Recordid Price  Start date    end date 
-----------------------------------------
1        20     2017-10-01    2017-10-02
2        20     2017-10-03    2017-10-04
3        30     2017-10-05    2017-10-05
4        20     2017-10-06    2017-10-07
我想得到每一个价格时,它开始和结束,所以我的结果集将是

20.  2017-10-01.  2017-10-04
30.  2017-10-05.  2017-10-05
20.  2017-10-06.  2017-10-07
我很难弄明白


这是一个Oracle数据库

以下是一种可能适用于您的情况的方法:

select price, min(start_date), max(end_date)
from (select t.*,
             sum(case when prev_price = price and prev_end_date = start_date - 1
                      then 0 else 1
                 end) over (order by t.start_date) as grp
      from (select t.*,
                   lag(t.end_date) over (order by t.start_date) as prev_end_date,
                   lag(t.price) over (order by t.start_date) as prev_price
            from t
           ) t
     ) t
group by price, grp

从您的示例数据中,我认为您希望在价格按照记录id的顺序进行更改时获得开始日期和结束日期。 由于可读性,以下查询可能包含的子查询多于必需的子查询。最内部的选择决定了什么时候价格发生了变化,这里称之为组变化。下一级通过滚动求和从组中删除。这是可能的,因为只有组更改包含大于0的值。剩下的是显而易见的

SELECT GRP, 
       PRICE, 
       MIN("Start date") AS "Start date", 
       MAX("end date") AS "end date"
  FROM ( SELECT sub.*,
                SUM(GROUP_CHANGE) OVER (ORDER BY RECORDID) AS GRP
           FROM ( SELECT t.*,
                         CASE 
                            WHEN RECORDID = LAG(t.RECORDID) OVER (ORDER BY t.PRICE, t.RECORDID) + 1 
                               THEN 0 
                            ELSE RECORDID 
                         END AS GROUP_CHANGE
                    FROM t ) sub ) fin
 GROUP BY GRP, PRICE 
 ORDER BY GRP


       GRP      PRICE Start date end date
---------- ---------- ---------- --------
         1         20 01.10.17   04.10.17 
         4         30 05.10.17   05.10.17 
         8         20 06.10.17   11.10.17 
使用以下数据进行测试注意,我已经向deliverd示例数据添加了一些记录,因为我希望有一个包含三条记录的组

CREATE TABLE t (
   Recordid     INT,
   Price        INT, 
   "Start date" DATE,
   "end date"   DATE 
);

INSERT INTO t VALUES (1,        20,     TO_DATE('2017-10-01', 'YYYY-MM-DD'),    TO_DATE('2017-10-02', 'YYYY-MM-DD'));
INSERT INTO t VALUES (2,        20,     TO_DATE('2017-10-03', 'YYYY-MM-DD'),    TO_DATE('2017-10-04', 'YYYY-MM-DD'));
INSERT INTO t VALUES (3,        30,     TO_DATE('2017-10-05', 'YYYY-MM-DD'),    TO_DATE('2017-10-05', 'YYYY-MM-DD'));
INSERT INTO t VALUES (4,        20,     TO_DATE('2017-10-06', 'YYYY-MM-DD'),    TO_DATE('2017-10-07', 'YYYY-MM-DD'));
INSERT INTO t VALUES (5,        20,     TO_DATE('2017-10-08', 'YYYY-MM-DD'),    TO_DATE('2017-10-09', 'YYYY-MM-DD'));
INSERT INTO t VALUES (6,        20,     TO_DATE('2017-10-10', 'YYYY-MM-DD'),    TO_DATE('2017-10-11', 'YYYY-MM-DD'));

我用下面的代码算出了

SELECT distinct price
      , case when start_dt is null then lag(start_dt) over (order by start_date) 
             else start_dt end realstart
      , case when end_dt is null then lead(end_dt) over (order by end_date) 
             else  end_dt end realend   
FROM (SELECT case when nvl(lag(price) over (order by start_date),-1) <> price then start_date end start_dt
           , case when nvl(lead(price) over (order by end_date),-1) <>price then end_date end end_dt
           , price 
           , start_date
           , end_date 
       FROM t) main 
WHERE start_dt is not null 
   or end_dt is not null

我不懂规则。如何确定价格20的两个输出记录?简单的第一,价格从第一个记录到第四个记录是20,作为前两个记录说,然后是一天30,作为int,第三个记录,然后是两天20,再次作为第四个记录基本上我需要一种方法将前两个记录与第四个记录分开,但我在计算上有困难原始表中的每条记录代表什么?这不是价格变化,因为记录1和记录2将由单个记录表示,该记录看起来像1 | 20 | 2017-10-01 | 2017-10-04,它有更多的数据列,并且每次拆分的任何列发生变化时,我看不出这应该解决它,您将1分配给第一个记录,0分配给第二个记录所以当你把它分组时,你得到了所有四个records@JacobGoldhirsch . . . 有一个你没有考虑的累积总数。好的,我明天会测试它。我测试了它,正如我昨天说的,它不会解决任何问题。使用{}图标在所见即所得编辑器或ctrl-K中放入代码块,我相信。谢谢!我很感激