3

Say I've got a table with two columns (date and price). If I select over a range of dates, then is there a way to count the number of price changes over time?

For instance:

   Date   | Price
22-Oct-11 |  3.20
23-Oct-11 |  3.40
24-Oct-11 |  3.40
25-Oct-11 |  3.50
26-Oct-11 |  3.40
27-Oct-11 |  3.20
28-Oct-11 |  3.20

In this case, I would like it to return a count of 4 price changes.

Thanks in advance.

Jama
  • 295
  • 4
  • 9

3 Answers3

5

You can use the analytic functions LEAD and LAG to access to prior and next row of a result set and then use that to see if there are changes.

SQL> ed
Wrote file afiedt.buf

  1  with t as (
  2    select date '2011-10-22' dt, 3.2 price from dual union all
  3    select date '2011-10-23', 3.4 from dual union all
  4    select date '2011-10-24', 3.4 from dual union all
  5    select date '2011-10-25', 3.5 from dual union all
  6    select date '2011-10-26', 3.4 from dual union all
  7    select date '2011-10-27', 3.2 from dual union all
  8    select date '2011-10-28', 3.2 from dual
  9  )
 10  select sum(is_change)
 11    from (
 12      select dt,
 13             price,
 14             lag(price) over (order by dt) prior_price,
 15             (case when lag(price) over (order by dt) != price
 16                   then 1
 17                   else 0
 18               end) is_change
 19*       from t)
SQL> /

SUM(IS_CHANGE)
--------------
             4
Justin Cave
  • 227,342
  • 24
  • 367
  • 384
0

Try this

select count(*)
from 
(select date,price from table where date between X and Y
 group by date,price )
Sparky
  • 14,967
  • 2
  • 31
  • 45
  • 3
    It looks like you're trying to count the number of distinct prices not the number of price changes. The change from 3.2 to 3.4 on 10/23 is one change and the change from 3.5 to 3.4 on 10/26 is a second change so there are 4 price changes even though there are only 3 distinct prices. But then you're grouping by `DATE` in addition to `PRICE` so you end up just counting the rows between the two dates (7 in this case) assuming one price per date. – Justin Cave Nov 08 '11 at 20:26
0

Depending on the Oracle version use either analytical functions (see answer from Justin Cave) or this

SELECT 
SUM (CASE WHEN PREVPRICE != PRICE THEN 1 ELSE 0 END) CNTCHANGES
FROM
(
SELECT
C.DATE,
C.PRICE,
MAX ( D.PRICE ) PREVPRICE
FROM
(
SELECT 
A.Date, 
A.Price,
(SELECT MAX (B.DATE) FROM MyTable B WHERE B.DATE < A.DATE) PrevDate
FROM MyTable A
WHERE A.DATE BETWEEN YourStartDate AND YourEndDate
) C
INNER JOIN MyTable D ON D.DATE = C.PREVDATE
GROUP BY C.DATE, C.PRICE
)
Yahia
  • 69,653
  • 9
  • 115
  • 144