sql >> Database teknologi >  >> RDS >> PostgreSQL

Sådan tilføjes en løbende optælling til rækker i en 'stribe' af på hinanden følgende dage

Bygger på denne tabel (bruger ikke SQL-søgeordet "dato" som kolonnenavn.):

CREATE TABLE tbl(
  pid int
, the_date date
, PRIMARY KEY (pid, the_date)
);

Forespørgsel:

SELECT pid, the_date
     , row_number() OVER (PARTITION BY pid, grp ORDER BY the_date) AS in_streak
FROM  (
   SELECT *
        , the_date - '2000-01-01'::date
        - row_number() OVER (PARTITION BY pid ORDER BY the_date) AS grp
   FROM   tbl
) sub
ORDER  BY pid, the_date;

At trække en date fra fra en anden date giver et integer . Da du leder efter på hinanden følgende dage, ville hver næste række være én større . Hvis vi trækker row_number() fra fra det ender hele streaken i den samme gruppe (grp ) pr. pid . Så er det nemt at uddele antal pr. gruppe.

grp beregnes med to subtraktioner, som skal være hurtigst. Et lige så hurtigt alternativ kunne være:

the_date - row_number() OVER (PARTITION BY pid ORDER BY the_date) * interval '1d' AS grp

En multiplikation, en subtraktion. Strengesammenkædning og støbning er dyrere. Test med EXPLAIN ANALYZE .

Glem ikke at partitionere efter pid desuden i begge trin, eller du vil uforvarende blande grupper, der burde adskilles.

Brug af en underforespørgsel, da det typisk er hurtigere end en CTE . Der er intet her, som en almindelig underforespørgsel ikke kunne gøre.

Og siden du nævnte det:dense_rank() er åbenbart ikke nødvendigt her. Grundlæggende row_number() gør jobbet.



  1. Er brug af char som primær/fremmednøgle et nej nej?

  2. Hvordan demonstrerer man SQL Injection i denne PHP- og MySQL-kode?

  3. Hvordan udfører jeg automatisk et MySQL script eller rutine efter videreudvikling fra model

  4. Sådan maskerer du Cassandra med IRI FieldShield