sql >> Database teknologi >  >> RDS >> Oracle

Oracle SQL - Vælg brugere mellem to dato for måned

Denne forespørgsel viser antallet af aktive brugere, der er gældende fra slutningen af ​​måneden.

Sådan fungerer det:

  1. Konverter hver inputrække (med StartDate og Slutdato værdi) i to rækker, der repræsenterer et tidspunkt, hvor antallet af aktive brugere steg (på Startdato ) og dekrementeret (på Slutdato ). Vi skal konvertere NULL til en fjern datoværdi, fordi NULL værdier sorteres før i stedet for efter ikke-NULL værdier:

    Dette får dine data til at se sådan ud:

    OnThisDate Change2018-01-01 12019-01-01 -12018-01-01 19999-12-31 -12019-01-01 12019-06-01 -12017-01-091 03-01 -1
  2. SUMMER vi simpelthen Skift værdier (efter sortering) for at få antallet af aktive brugere fra den specifikke dato:

    Så først sorter efter OnThisDate :

    OnThisDate Change2017-01-01 12018-01-01 12018-01-01 12019-01-01 12019-01-01 -12019-03-01 -12019-06-091 -19-19-19-19 -1 

    Derefter SUM OVER :

    OnThisDate ActiveCount2017-01-01 12018-01-01 22018-01-01 32019-01-01 42019-01-01 32019-03-01 22019-06-01 029  
  3. PARTITION (ikke grupper!) rækkerne efter måned og sorter dem efter deres dato, så vi kan identificere den sidste ActiveCount række for den måned (dette sker faktisk i WHERE af den yderste forespørgsel ved hjælp af ROW_NUMBER() og COUNT() for hver måned PARTITION ):

    OnThisDate ActiveCount IsLastInMonth2017-01-01 1 12018-01-01 2 02018-01-01 3 12019-01-01 4 02019-01-01 3 12019-2030-12019-203 1999-12-31 0 1 
  4. Filtrer derefter på det, hvor IsLastInMonth =1 (faktisk hvor ROW_COUNT() =COUNT(*) inde i hver PARTITION ) for at give os de endelige outputdata:

    Aktivt antal ved månedens slutning2017-01 12018-01 32019-01 32019-03 22019-06 19999-12 0 

Dette resulterer i "huller" i resultatsættet, fordi Ved-af-måned kolonne viser kun rækker, hvor Active-count værdi faktisk ændret i stedet for at inkludere alle mulige kalendermåneder - men det er ideelt (så vidt jeg er bekymret for), fordi det udelukker overflødige data. Du kan udfylde hullerne i din applikationskode ved blot at gentage outputrækker for hver ekstra måned, indtil den når den næste Ved udgangen af ​​måneden værdi.

Her er forespørgslen, der bruger T-SQL på SQL Server (jeg har ikke adgang til Oracle lige nu). Og her er den SQLFiddle, jeg brugte til at finde en løsning:http://sqlfiddle.com/# !18/ad68b7/24

SELECT OtdYear, OtdMonth, ActiveCountFROM ( -- Denne forespørgsel tilføjer kolonner for at angive, hvilken række der er den sidste række-i-måned (hvor RowInMonth ==RowsInMonth ) SELECT OnThisDate, OtdYear, OtdMonth, ROW_NUMBER() ( PARTITION BY OtdYear, OtdMonth ORDER BY OnThisDate ) AS RowInMonth, COUNT(*) OVER ( PARTITION BY OtdYear, OtdMonth ) AS RowsInMonth, ActiveCounte FROM (SELECT OnThisDate, YEAR) AS ThisMonth(OtdMonth) [Skift] ) OVER ( BESTIL AF OnThisDate ASC ) AS ActiveCount FROM ( SELECT StartDate AS [OnThisDate], 1 AS [Change] FROM tbl UNION ALL SELECT ISNULL( EndDate, DATEFROMPARTS( 9999, 12, 31 ) ), AS [OnThisDate] -1 AS [Skift] FRA tbl ) AS sq1 ) AS sq2 ) AS sq3WHERE RowInMonth =RowsIn MonthORDER BY OtdYear, OtdMonth 

Denne forespørgsel kan udjævnes til færre indlejrede forespørgsler ved at bruge aggregat- og vinduesfunktioner direkte i stedet for at bruge aliaser (som OtdYear , ActiveCount osv.), men det ville gøre forespørgslen meget sværere at forstå.



  1. Hvorfor er MySQL's data_free større end data og indekser tilsammen?

  2. Migration udenlandsk nøgle vs veltalende forhold i Laravel

  3. Brug af dvaleværktøjer til at omdanne pojos fra Postgres

  4. Hvordan erstatter man specifikke værdier i en oracle database kolonne?