oracle sql - 编号行组

时间:2014-09-16 08:10:41

标签: sql oracle analytic-functions

我的下表中每周都有不同的价格,需要像上一栏中的编号一样。具有相同价格的连续行应具有相同的数字,如11/12或18/19周。但另一方面,第2周和第16周的价格相同但不连续,所以他们应该得到不同的数字。

w | price    | r1 | need
===========================
1   167,93     1    1
2   180        1    2
3   164,72     1    3
4   147,42     1    4
5   133,46     1    5
6   145,43     1    6
7   147        1    7
8   147,57     1    8
9   150,95     1    9
10  158,14     1    10
11  170        1    11
12  170        2    11
13  166,59     1    12
14  161,06     1    13
15  162,88     1    14
16  180        2    15
17  183,15     1    16
18  195        1    17
19  195        2    17

我已经尝试过分析功能(row_number,rank,dens_rank),但到目前为止还没有找到解决此问题的方法。

(oracle sql 10,11)

有人有提示吗?感谢。

5 个答案:

答案 0 :(得分:5)

首先模拟你的桌子:

SQL> create table mytable (w,price,r1)
  2  as
  3  select 1 , 167.93, 1 from dual union all
  4  select 2 , 180   , 1 from dual union all
  5  select 3 , 164.72, 1 from dual union all
  6  select 4 , 147.42, 1 from dual union all
  7  select 5 , 133.46, 1 from dual union all
  8  select 6 , 145.43, 1 from dual union all
  9  select 7 , 147   , 1 from dual union all
 10  select 8 , 147.57, 1 from dual union all
 11  select 9 , 150.95, 1 from dual union all
 12  select 10, 158.14, 1 from dual union all
 13  select 11, 170   , 1 from dual union all
 14  select 12, 170   , 2 from dual union all
 15  select 13, 166.59, 1 from dual union all
 16  select 14, 161.06, 1 from dual union all
 17  select 15, 162.88, 1 from dual union all
 18  select 16, 180   , 2 from dual union all
 19  select 17, 183.15, 1 from dual union all
 20  select 18, 195   , 1 from dual union all
 21  select 19, 195   , 2 from dual
 22  /

Table created.

您的需求列分为两部分计算:首先计算增量列,该列表示上一个价格列是否与当前行价格列不同。如果你有delta列,那么通过计算这些delta的总和就可以轻松实现第二部分。

SQL> with x as
  2  ( select w
  3         , price
  4         , r1
  5         , case lag(price,1,-1) over (order by w)
  6           when price then 0
  7           else 1
  8           end delta
  9      from mytable
 10  )
 11  select w
 12       , price
 13       , r1
 14       , sum(delta) over (order by w) need
 15    from x
 16  /

         W      PRICE         R1       NEED
---------- ---------- ---------- ----------
         1     167.93          1          1
         2        180          1          2
         3     164.72          1          3
         4     147.42          1          4
         5     133.46          1          5
         6     145.43          1          6
         7        147          1          7
         8     147.57          1          8
         9     150.95          1          9
        10     158.14          1         10
        11        170          1         11
        12        170          2         11
        13     166.59          1         12
        14     161.06          1         13
        15     162.88          1         14
        16        180          2         15
        17     183.15          1         16
        18        195          1         17
        19        195          2         17

19 rows selected.

答案 1 :(得分:2)

您可以使用内联视图嵌套分析函数,因此首先使用相同的价格对连续的周进行分组,然后使用这些组对dense_rank进行分组:

select w
     , price
     , r1
     , dense_rank() over (
          order by first_w_same_price
       ) drank
  from (
   select w
        , price
        , r1
        , last_value(w_start_same_price) ignore nulls over (
             order by w
             rows between unbounded preceding and current row
          ) first_w_same_price
     from (
      select w
           , price
           , r1
           , case lag(price) over (order by w)
                when price then null
                else w
             end w_start_same_price
        from your_table
     )
  )
 order by w

具有LAG功能的最里面的内联视图允许每个连续组的起始周获得它自己的周数,但是相同价格的每个连续周都变为空(数据中的第12周和第19周)。

使用LAST_VALUE函数的中间内联视图然后使用IGNORE NULLS功能为连续周提供与每个组中第一周相同的值。所以第11周和第12周在first_w_same_price中获得11,第18周和第19周在first_w_same_price中获得18。

最后外部查询使用DENSE_RANK来提供所需的结果。

答案 2 :(得分:0)

对于每一行,您应该计算前一行,其中(w-1)行价与(w)价格相同:

select T1.*,
(SELECT count(*) 
  FROM T T2
    JOIN T T3 ON T2.w-1=T3.w
    WHERE T2.Price<>T3.Price
          AND T2.W<=T1.W)+1 rn

from t T1

SQLFiddle demo

答案 3 :(得分:0)

试试这个:

with tt as (
  select t.*, decode(lag(price) over(order by w) - price, 0, 1, 0) diff
    from t
)
select w
     , price
     , r1
     , row_number() over (order by w) - sum(diff) over(order by w rows between UNBOUNDED PRECEDING and current row) need
  from tt

答案 4 :(得分:-1)

SELECT  w, price, r1, 
       ROW_NUMBER ()  OVER (PARTITION BY price ORDER BY price) row_column
FROM TABLE