1

I have a table with 12 registers. I want to count the row just if the column "AREA_OPERATIVA" is different from the previous row (ordering by date asc).

table

For example, from row 1 to row 2 it shouldn't count anything because both have same area 'CROSS' but between rows 2 and 3, it should count (or sum 1, I don't care) since 'CROSS' and 'UTRDANIOS' are different. So the final count should be 3 for the whole table.

Is it possible to do this via query or do I need to make a script with a cursor for this purpose?

I've tried this:

SELECT  a.creclama, 
sum (CASE WHEN b.area_operativa  NOT LIKE  a.area_operativa THEN 1 ELSE 0 END) AS increment
FROM TR_ASGAREOPE a
INNER JOIN TR_ASGAREOPE b ON a.creclama = b.creclama 
                          and a.cdistribuidora = b.cdistribuidora 
                          and a.secuencia = b.secuencia
WHERE a.creclama = 10008354
group by a.creclama;

But is counting the full 12 rows.

EDIT:

Finally I could resolve this by the next query:

select sum (
    CASE WHEN (comparacion.area_operativa  not like  comparacion.siguiente_fila THEN 1 ELSE 0 END) AS incremento 
from (    
    select creclama,
           area_operativa, 
           lead(area_operativa) over (order by fmodifica) as siguiente_fila
    from TR_ASGAREOPE
    where creclama = 10008354
    order by fmodifica
);

Hope it is useful for someone in the future, it really got me stuck for a day. Thank you all guys.

Barbaros Özhan
  • 59,113
  • 10
  • 31
  • 55
  • 3
    Please post text rather than images; and include the current and expected output. The current query is joining each row to itself, not the 'previous one'. You might be looking for lead/lag, but it's not entirely clear. And which date are you using to decide the order? – Alex Poole Aug 08 '19 at 09:13
  • I will do the way u suggest from now. Finally I could resolve the problem with lead, thank you so much. – Amiquemeregistren Aug 08 '19 at 12:28

4 Answers4

4

You could try using analytic functions like lead or lag, for example

    SELECT CRECLAMA,
           CASE WHEN AREA_OPERATIVA <> NEXTROW THEN 1 ELSE 0 END AS INCREMENT
      FROM (
            SELECT CRECLAMA,
                   AREA_OPERATIVA,
                   LEAD(AREA_OPERATIVA) OVER (PARTITION BY 1 ORDER BY CRECLAMA) AS NEXTROW
              FROM TR_ASGAREOPE
            )
MarEll
  • 296
  • 2
  • 9
1

You can use lag() analytic function :

with t as
(
 select a.*,
        lag(a.area_operativa,1,a.area_operativa) over (order by a."date") as lg
   from asgareope a
  where a.creclama = 10008354
)   
select t.creclama, sum(case when lg = area_operativa then 0 else 1 end) as "increment"
  from t     
 group by t.creclama
Barbaros Özhan
  • 59,113
  • 10
  • 31
  • 55
1

Here's an approach using LEAD:

WITH TR_ASGAREOPE(CRECLAMA, AREA_OPERATIVA, DATE_FIELD) AS
                 (SELECT 10008354, 'CROSS', DATE '2019-01-01' FROM DUAL UNION ALL
                  SELECT 10008354, 'CROSS', DATE '2019-01-02' FROM DUAL UNION ALL      -- 1
                  SELECT 10008354, 'UTRDANIOS', DATE '2019-01-03' FROM DUAL UNION ALL  -- 2
                  SELECT 10008354, 'EXP263', DATE '2019-01-04' FROM DUAL UNION ALL     -- 3
                  SELECT 10008354, 'EXP6', DATE '2019-01-05' FROM DUAL UNION ALL
                  SELECT 10008354, 'EXP6', DATE '2019-01-06' FROM DUAL UNION ALL
                  SELECT 10008354, 'EXP6', DATE '2019-01-07' FROM DUAL UNION ALL
                  SELECT 10008354, 'EXP6', DATE '2019-01-08' FROM DUAL UNION ALL
                  SELECT 10008354, 'EXP6', DATE '2019-01-09' FROM DUAL UNION ALL
                  SELECT 10008354, 'EXP6', DATE '2019-01-10' FROM DUAL UNION ALL
                  SELECT 10008354, 'EXP6', DATE '2019-01-11' FROM DUAL UNION ALL
                  SELECT 10008354, 'EXP6', DATE '2019-01-12' FROM DUAL UNION ALL
                  SELECT 12345678, 'AREA49', DATE '2019-02-01' FROM DUAL UNION ALL
                  SELECT 12345678, 'AREA49', DATE '2019-02-02' FROM DUAL UNION ALL  -- 1
                  SELECT 12345678, 'AREA50', DATE '2019-02-03' FROM DUAL UNION ALL
                  SELECT 12345678, 'AREA50', DATE '2019-02-04' FROM DUAL UNION ALL  -- 2
                  SELECT 12345678, 'AREA52', DATE '2019-02-05' FROM DUAL UNION ALL
                  SELECT 12345678, 'AREA52', DATE '2019-02-06' FROM DUAL UNION ALL
                  SELECT 12345678, 'AREA52', DATE '2019-02-07' FROM DUAL UNION ALL  -- 3
                  SELECT 12345678, 'AREA53', DATE '2019-02-08' FROM DUAL UNION ALL  -- 4
                  SELECT 12345678, 'AREA52', DATE '2019-02-09' FROM DUAL UNION ALL  -- 5
                  SELECT 12345678, 'AREA53', DATE '2019-02-10' FROM DUAL),
     cteData AS (SELECT CRECLAMA,
                         LEAD(CRECLAMA) OVER (ORDER BY DATE_FIELD) AS NEXT_CRECLAMA,
                         AREA_OPERATIVA,
                         LEAD(AREA_OPERATIVA) OVER (ORDER BY DATE_FIELD) AS NEXT_AREA_OPERATIVA
                    FROM TR_ASGAREOPE)
SELECT CRECLAMA, COUNT(*)
  FROM cteData
  WHERE CRECLAMA = NEXT_CRECLAMA AND
        AREA_OPERATIVA <> NEXT_AREA_OPERATIVA
  GROUP BY CRECLAMA
  ORDER BY CRECLAMA;

I added data for another CRECLAMA value to show how it would work.

Results:

CRECLAMA    COUNT(*)
10008354    3
12345678    5

dbfiddle here

0

I think you can simple use COUNT(DISTINCT ...) for your problem, if the AREA_OPERATIVA could not return to previously used value:

SELECT CRECLAMA, COUNT(DISTINCT AREA_OPERATIVA)
  FROM TR_ASGAREOPE
 GROUP BY CRECLAMA
Radagast81
  • 2,921
  • 1
  • 7
  • 21
  • 1
    This will not produce the correct value if values return to previous values. – Gordon Linoff Aug 08 '19 at 11:10
  • 1
    This just returns the number of different values of 'AREA_OPERATIVA' for that 'CRECLAMA'. – Amiquemeregistren Aug 08 '19 at 12:27
  • You are absolutely right. Might none the less be the simpliest solution depending on the dataset - so I just added the additional condition. Allthough it doesn't solve your problem it might be the way to go in a similar case... – Radagast81 Aug 08 '19 at 12:50