sql >> Database >  >> RDS >> Oracle

Oracle SQL - Identificeer opeenvolgende waardebereiken

Dit is gemakkelijk te doen met een techniek genaamd Tabibitosan.

Wat deze techniek doet, is de posities van de rijen van elke groep vergelijken met de totale reeks rijen, om te bepalen of rijen in dezelfde groep naast elkaar liggen of niet.

Met uw voorbeeldgegevens ziet dit er bijvoorbeeld als volgt uit:

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

Hier heb ik alle rijen over de hele set gegevens een rijnummer gegeven in oplopende id-volgorde (de overall_rn kolom), en ik heb de rijen in elke afdeling een rijnummer gegeven (de department_rn kolom), opnieuw in oplopende ID-volgorde.

Nu ik dat heb gedaan, kunnen we de een van de ander aftrekken (de grp kolom).

Merk op hoe het getal in de kolom grp hetzelfde blijft voor naast elkaar gelegen afdelingsrijen, maar het verandert elke keer dat er een opening is.

bijv. voor de afdeling Marketing liggen de rijen 1-3 naast elkaar en hebben grp =0, maar de 4e rij Marketing staat eigenlijk op de 5e rij van de totale resultatenset, dus deze heeft nu een ander grp-nummer. Aangezien de 5e marketingrij zich op de 6e rij van de totale set bevindt, heeft deze hetzelfde grp-nummer als de 4e marketingrij, dus we weten dat ze naast elkaar staan.

Zodra we die grp-informatie hebben, is het een kwestie van een geaggregeerde querygroepering op zowel de afdeling als onze nieuwe grp-kolom, met min en max om de begin- en eind-id's te vinden:

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., ik ben ervan uitgegaan dat gaten in de id-kolommen niet belangrijk zijn (d.w.z. als er geen rij was voor id =6 (dus Leo en Kevin's id's waren respectievelijk 7 en 8), dan zouden Leo en Brad nog steeds in dezelfde groep, met een start-id =5 en eind-id =7.

Als hiaten in de id-kolommen tellen als aanduiding van een nieuwe groep, kunt u de id gewoon gebruiken om de algemene reeks rijen te labelen (d.w.z. u hoeft de overall_rn niet te berekenen; gebruik in plaats daarvan gewoon de id-kolom).

Dat betekent dat uw vraag zou worden:

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. Wat is de maximale grootte voor een varchar2 PL/SQL-subprogrammaargument in Oracle?

  2. Hoe vind je vergelijkbare resultaten en sorteer je op overeenkomst?

  3. Relatie tussen catalogus, schema, gebruiker en database-instantie

  4. Toegang krijgen tot verloren MySQL-wachtwoord voor PHPMyAdmin op WAMP