Oracle
 sql >> база данни >  >> RDS >> Oracle

SQL заявка за преброяване на промените на стойностите в колона

От Oracle 12 можете да използвате MATCH_RECOGNIZE :

SELECT cat,
       month,
       COUNT(*)
FROM   (
  SELECT t.*,
         TRUNC( "DATE", 'MM' ) AS month
  FROM   table_name t
)
MATCH_RECOGNIZE(
  PARTITION BY cat, month
  ORDER BY "DATE", version
  ONE ROW PER MATCH
  AFTER MATCH SKIP TO LAST change_code
  PATTERN ( strt change_code )
  DEFINE
    change_code AS change_code.some_code <> strt.some_code
)
GROUP BY cat, month

Което за примерните данни:

CREATE TABLE table_name ( CAT, NR, "DATE", VERSION, SOME_CODE ) AS
SELECT 'ABC',   123,    TIMESTAMP '2009-02-19 00:00:00 UTC',    1,  'OPP' FROM DUAL UNION ALL
SELECT 'ABC',   456,    TIMESTAMP '2009-03-18 00:00:00 UTC',    1,  'ZUM' FROM DUAL UNION ALL
SELECT 'ABC',   444,    TIMESTAMP '2009-03-18 00:00:00 UTC',    1,  'ZUM' FROM DUAL UNION ALL
SELECT 'ABC',   444,    TIMESTAMP '2009-03-18 00:00:00 UTC',    2,  'MUZ' FROM DUAL UNION ALL
SELECT 'ABC',   456,    TIMESTAMP '2009-04-18 00:00:00 UTC',    2,  'XXX' FROM DUAL UNION ALL
SELECT 'ABC',   456,    TIMESTAMP '2009-04-18 00:00:00 UTC',    3,  'XXX' FROM DUAL UNION ALL
SELECT 'ABC',   456,    TIMESTAMP '2009-04-18 00:00:00 UTC',    4,  'UIO' FROM DUAL UNION ALL
SELECT 'ABC',   456,    TIMESTAMP '2009-05-18 00:00:00 UTC',    5,  'RQA' FROM DUAL UNION ALL
SELECT 'DEF',   637,    TIMESTAMP '2018-02-16 00:00:00 UTC',    1,  'FAW' FROM DUAL UNION ALL
SELECT 'DEF',   789,    TIMESTAMP '2018-02-17 00:00:00 UTC',    1,  'WER' FROM DUAL UNION ALL
SELECT 'GHI',   248,    TIMESTAMP '2018-02-17 00:00:00 UTC',    1,  'QWE' FROM DUAL UNION ALL
SELECT 'GHI',   248,    TIMESTAMP '2019-02-17 00:00:00 UTC',    2,  'PPP' FROM DUAL UNION ALL
SELECT 'GHI',   357,    TIMESTAMP '2020-02-16 00:00:00 UTC',    1,  'FFF' FROM DUAL UNION ALL
SELECT 'GHI',   420,    TIMESTAMP '2020-02-16 00:00:00 UTC',    1,  'QDS' FROM DUAL UNION ALL
SELECT 'GHI',   357,    TIMESTAMP '2020-02-16 00:00:00 UTC',    2,  'GGG' FROM DUAL UNION ALL
SELECT 'GHI',   357,    TIMESTAMP '2020-02-16 00:00:00 UTC',    3,  'LLL' FROM DUAL UNION ALL
SELECT 'GHI',   357,    TIMESTAMP '2020-02-16 00:00:00 UTC',    4,  'LLL' FROM DUAL UNION ALL
SELECT 'GHI',   357,    TIMESTAMP '2020-08-16 00:00:00 UTC',    4,  'FFF' FROM DUAL UNION ALL
SELECT 'GHI',   357,    TIMESTAMP '2020-10-16 00:00:00 UTC',    5,  'ZZZ' FROM DUAL

Изходи:

Ако искате да видите промените, можете да използвате:

SELECT *
FROM   (
  SELECT t.*,
         TRUNC( "DATE", 'MM' ) AS month
  FROM   table_name t
)
MATCH_RECOGNIZE(
  PARTITION BY cat, month
  ORDER BY "DATE", version
  MEASURES
    MATCH_NUMBER()     AS mn,
    FIRST( some_code ) AS change_from,
    LAST( some_code )  AS change_to
  ONE ROW PER MATCH
  AFTER MATCH SKIP TO LAST change_code
  PATTERN ( strt change_code )
  DEFINE
    change_code AS change_code.some_code <> strt.some_code
)

Кое извежда:

db<>fiddle тук

Ако вашето изискване за „в рамките на един месец“ е, че искате промени, при които има най-много един месец разлика между предишния ред и променения ред, дори ако редовете са в два различни календарни месеца (а не само промените, които се случват през същия календарен месец), тогава можете да използвате:

SELECT cat,
       TRUNC( change_date, 'MM' ) AS month,
       COUNT(*)
FROM   table_name
MATCH_RECOGNIZE(
  PARTITION BY cat
  ORDER BY "DATE", version
  MEASURES
    LAST( "DATE" ) AS change_date
  ONE ROW PER MATCH
  AFTER MATCH SKIP TO LAST change_code
  PATTERN ( strt change_code )
  DEFINE
    change_code AS (
      change_code.some_code <> strt.some_code
      AND MONTHS_BETWEEN( change_code."DATE", strt."DATE" ) <= 1
    )
)
GROUP BY cat, TRUNC( change_date, 'MM' )

Кое извежда:

db<>fiddle тук



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да използвате асоциативен масив на Oracle в SQL заявка

  2. Практически житейски примери за явно използване на курсора на Oracle

  3. Как да реша ORA-29471 на dbms_sql.open_cursor?

  4. Списък с NLS параметри в базата данни на Oracle

  5. Промяна на стойността на XML възел - UpdateXML еквивалент за Oracle 12c