sql >> Databasteknik >  >> RDS >> PostgreSQL

PostgreSQL - Hämta statistisk data

Du bör titta på aggregerade funktioner (min, max, count, avg), som går hand i hand med GROUP BY . För datumbaserade aggregationer, date_trunc är också användbart.

Till exempel kommer detta att returnera antalet rader per dag:

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

Du kan sedan göra det dagliga genomsnittet med något sånt här (med en 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;

Använd 'week' istället för dag för veckoräkningar, och så vidare (se date_trunc dokumentation).

EDIT: (Följande kommentar:genomsnitt till och med 5/1/2012, dvs före den 6.)

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;

Vad som står ovan är alltför komplicerat, i det här fallet. Detta bör ge dig samma resultat:

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');

EDIT 2: Efter din redigering antar jag att det du är ute efter bara är ett enda globalt genomsnitt för hela din databas existens, snarare än grupperingar efter månad/vecka/dag.

Detta bör ge dig det genomsnittliga antalet rader per dag:

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

(Jag skulle ersätta last_date_time med NOW() för att göra genomsnittet över tiden fram till nu, snarare än fram till det senaste besöket, om det inte finns något nyligen besök.)

Sedan, för dagligen, veckovis och "månadsvis":

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

Med detta sagt, slutsatser du drar från sådan statistik kanske inte är bra, särskilt om du vill se hur den förändras.

Jag skulle också normalisera data per dag i stället för att anta 30 dagar i en månad (om inte per timme, eftersom inte alla dagar har 24 timmar ). Säg att du har 10 besök per dag i januari 2011 och 10 besök per dag i februari 2011. Det ger dig 310 besök i januari och 280 besök i februari. Om du inte är uppmärksam kan du tro att du har haft en nästan en 10 % minskning i antal besökare, så något gick fel i februari, när det verkligen inte är fallet.




  1. Hur kan jag återställa mitt senaste raderingskommando i MySQL?

  2. MySQL:fel i din SQL-syntax | GRÄNS 0, 25

  3. Att hitta den närmaste numeriska matchningen i en databas till vad en användare har skrivit in i php

  4. Olika representation av UUID i Java Hibernate och SQL Server