sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL - Statistische gegevens verkrijgen

Je zou moeten kijken naar geaggregeerde functies (min, max, count, avg), die hand in hand gaan met GROUP BY . Voor op datum gebaseerde aggregaties, date_trunc is ook handig.

Dit geeft bijvoorbeeld het aantal rijen per dag terug:

SELECT date_trunc('day', date_time) AS day_start,
       COUNT(id) AS user_count FROM tb_user
    GROUP BY date_trunc('day', date_time);

Je kunt dan het dagelijkse gemiddelde doen met zoiets als dit (met een CTE ):

WITH daily_count AS (SELECT date_trunc('day', date_time) AS day_start,
       COUNT(id) AS user_count FROM tb_user
    GROUP BY date_trunc('day', date_time))
SELECT AVG(user_count) FROM daily_count;

Gebruik 'week' in plaats van dag voor de wekelijkse tellingen, enzovoort (zie date_trunc documentatie).

BEWERKEN: (Volgende opmerking:gemiddeld tot en met 1-5-2012, d.w.z. voor de 6e.)

WITH daily_count AS (SELECT date_trunc('day', date_time) AS day_start,
       COUNT(id) AS user_count
    FROM tb_user
       WHERE date_time >= DATE('2012-01-01') AND date_time < DATE('2012-01-06') 
    GROUP BY date_trunc('day', date_time))
SELECT SUM(user_count)/(DATE('2012-01-06') - DATE('2012-01-01')) FROM daily_count;

Wat hierboven staat is in dit geval te ingewikkeld. Dit zou u hetzelfde resultaat moeten geven:

SELECT COUNT(id)/(DATE('2012-01-06') - DATE('2012-01-01'))
    FROM tb_user
       WHERE date_time >= DATE('2012-01-01') AND date_time < DATE('2012-01-06');

BEWERK 2: Na je bewerking denk ik dat je op zoek bent naar slechts een enkel globaal gemiddelde voor de gehele bestaansperiode van je database, in plaats van groepen per maand/week/dag.

Dit zou u het gemiddelde aantal rijen per dag moeten geven:

WITH total_min_max AS (SELECT
        COUNT(id) AS total_visits,
        MIN(date_time) AS first_date_time,
        MAX(date_time) AS last_date_time,
    FROM tb_user)
SELECT total_visits/((last_date_time::date-first_date_time::date)+1) AS users_per_day
    FROM total_min_max

(Ik zou last_date_time vervangen met NOW() om het gemiddelde te maken over de tijd tot nu toe, in plaats van tot het laatste bezoek, als er geen recent bezoek is.)

Dan, voor dagelijks, wekelijks en "maandelijks":

WITH daily_avg AS (
    WITH total_min_max AS (SELECT
            COUNT(id) AS total_visits,
            MIN(date_time) AS first_date_time,
            MAX(date_time) AS last_date_time,
        FROM tb_user)
    SELECT total_visits/((last_date_time::date-first_date_time::date)+1) AS users_per_day
        FROM total_min_max)
SELECT
         users_per_day,
         (users_per_day * 7) AS users_per_week,
         (users_per_month * 30) AS users_per_month
    FROM daily_avg

Dit gezegd zijnde, de conclusies die je trekt uit dergelijke statistieken zijn misschien niet geweldig, vooral als je wilt zien hoe het verandert.

Ik zou ook de gegevens per dag normaliseren in plaats van 30 dagen in een maand aan te nemen (zo niet per uur, omdat niet alle dagen 24 uur hebben ). Stel dat u 10 bezoeken per dag heeft in januari 2011 en 10 bezoeken per dag in februari 2011. Dat geeft u 310 bezoeken in januari en 280 bezoeken in februari. Als u niet oplet, zou u kunnen denken dat u bijna een 10% daling qua aantal bezoekers, dus er ging iets mis in februari, terwijl dit echt niet het geval is.




  1. PDO execute array naar string conversiefout

  2. mysql-fout:subquery retourneert meer dan 1 rij

  3. Duplicaten verwijderen uit een grote tabel

  4. Gegevensclassificatie in IRI Workbench