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

Oracle SQL - Идентифицирайте последователни диапазони от стойности

Това е лесно да се направи с техника, наречена Табибитозан.

Това, което прави тази техника, е да сравнява позициите на редовете на всяка група с общия набор от редове, за да разберете дали редовете в същата група са един до друг или не.

Например с вашите примерни данни това изглежда така:

WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                    SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 6 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 7 ID, 'Kevin' NAME, 'Production' department FROM dual)
-- end of mimicking your table with data in it. See the SQL below:
SELECT ID,
       NAME,
       department,
       row_number() OVER (ORDER BY ID) overall_rn,
       row_number() OVER (PARTITION BY department ORDER BY ID) department_rn,
       row_number() OVER (ORDER BY ID) - row_number() OVER (PARTITION BY department ORDER BY ID) grp
FROM   your_table;

        ID NAME    DEPARTMENT OVERALL_RN DEPARTMENT_RN        GRP
---------- ------- ---------- ---------- ------------- ----------
         1 Michael Marketing           1             1          0
         2 Alex    Marketing           2             2          0
         3 Tom     Marketing           3             3          0
         4 John    Sales               4             1          3
         5 Brad    Marketing           5             4          1
         6 Leo     Marketing           6             5          1
         7 Kevin   Production          7             1          6

Тук съм дал на всички редове в целия набор от данни номер на ред във възходящ ред на идентификатора (overall_rn колона) и дадох на редовете във всеки отдел номер на ред (department_rn колона), отново във възходящ ред на идентификатора.

След като направих това, можем да извадим едното от другото (grp колона).

Забележете как числото в колоната grp остава същото за редовете на отделите, които са един до друг, но се променя всеки път, когато има празнина.

напр. за отдел „Маркетинг“, редове 1-3 са един до друг и имат grp =0, но 4-тият маркетингов ред всъщност е на 5-ия ред от общия набор от резултати, така че вече има различен gp номер. Тъй като 5-ият маркетингов ред е на 6-ия ред от общия набор, той има същият номер на групата като 4-ия маркетингов ред, така че знаем, че са един до друг.

След като имаме тази grp информация, е лесно да направим обобщено групиране на заявки както за отдела, така и за нашата нова колона grp, като използваме min и max за намиране на началния и крайния идентификатор:

WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                    SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 6 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 7 ID, 'Kevin' NAME, 'Production' department FROM dual)
-- end of mimicking your table with data in it. See the SQL below:
SELECT department,
       MIN(ID) start_id,
       MAX(ID) end_id
FROM   (SELECT ID,
               NAME,
               department,
               row_number() OVER (ORDER BY ID) - row_number() OVER (PARTITION BY department ORDER BY ID) grp
        FROM   your_table)
GROUP BY department, grp;

DEPARTMENT   START_ID     END_ID
---------- ---------- ----------
Marketing           1          3
Marketing           5          6
Sales               4          4
Production          7          7

N.B., предположих, че пропуските в колоните за идентификатор не са важни (т.е. ако нямаше ред за id =6 (така че идентификаторите на Лео и Кевин бяха съответно 7 и 8), тогава Лео и Брад все още биха се появявали в същото група, с начален идентификатор =5 и краен идентификатор =7.

Ако пропуските в колоните с идентификатор се считат за посочване на нова група, тогава можете просто да използвате идентификатора за етикетиране на общия набор от редове (т.е. няма нужда да изчислявате total_rn; просто използвайте колоната с идентификатор вместо това).

Това означава, че вашата заявка ще бъде:

WITH your_table AS (SELECT 1 ID, 'Michael' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 2 ID, 'Alex' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 3 ID, 'Tom' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 4 ID, 'John' NAME, 'Sales' department FROM dual UNION ALL
                    SELECT 5 ID, 'Brad' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 7 ID, 'Leo' NAME, 'Marketing' department FROM dual UNION ALL
                    SELECT 8 ID, 'Kevin' NAME, 'Production' department FROM dual)
-- end of mimicking your table with data in it. See the SQL below:
SELECT department,
       MIN(ID) start_id,
       MAX(ID) end_id
FROM   (SELECT ID,
               NAME,
               department,
               ID - row_number() OVER (PARTITION BY department ORDER BY ID) grp
        FROM   your_table)
GROUP BY department, grp;

DEPARTMENT   START_ID     END_ID
---------- ---------- ----------
Marketing           1          3
Sales               4          4
Marketing           5          5
Marketing           7          7
Production          8          8


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. .patch_storage

  2. Курсор за цикъл с динамичен SQL-изявление

  3. Java - Как да извика процедура на Oracle с персонализирани типове?

  4. Web Site Down и Twitter Feed

  5. Как да активирате регистриране за SQL изрази, когато използвате JDBC