Question

La requête ci-dessous regroupe les résultats de first dans 4 bacs de dates équidistants et regroupe en moyenne the_value dans chaque bac.

WITH first as(
SELECT
    extract(EPOCH FROM foo.t_date) as the_date,
    foo_val as the_value
FROM bar
INNER JOIN foo
ON
    foo.user_id = bar.x_id
    and
    foo.user_name = 'xxxx'
)
SELECT bin, round(sum(bin_sum) OVER w /sum(bin_ct) OVER w, 2) AS running_avg
FROM  (
   SELECT width_bucket(first.the_date
                     , x.min_epoch, x.max_epoch, x.bins) AS bin
        , sum(first.the_value) AS bin_sum
        , count(*)   AS bin_ct
   FROM   first
       , (SELECT MIN(first.the_date) AS min_epoch
               , MAX(first.the_date) AS max_epoch
               , 4 AS bins
          FROM  first
         ) x
   GROUP  BY 1
   ) sub
WINDOW w AS (ORDER BY bin)
ORDER  BY 1;

J'aimerais pouvoir calculer uniquement la moyenne des 20 les plus bas. the_valueest dans chaque bac.D'après d'autres articles ici sur Stackoverflow, j'ai vu que c'est possible et que peut-être ORDER BY the_value et rank() est la meilleure façon de procéder.Mais mon problème est que je ne sais pas où ma requête actuelle doit être modifiée pour implémenter cela.

Toute idée serait appréciée.

Postgres version 9.3

Était-ce utile?

La solution

Utiliser row_number() sur chaque bac.
Calculez d’abord le numéro de ligne rn, puis appliquez WHERE rn < 21 à l'étape suivante :

WITH first AS (
   SELECT extract(EPOCH FROM foo.t_date) AS the_date
        , foo_val AS the_value
   FROM bar
   JOIN foo ON foo.user_id = bar.x_id
           AND foo.user_name = 'xxxx'
   )
, x AS (
   SELECT MIN(the_date) AS min_epoch
        , MAX(the_date) AS max_epoch
   FROM  first
   )
, y AS (
   SELECT width_bucket(f.the_date, x.min_epoch, x.max_epoch, 4) AS bin, *
   FROM   first f, x
   )
, z AS (
   SELECT row_number() OVER (PARTITION BY bin ORDER BY the_value) AS rn, *
   FROM   y
   )
SELECT bin, round(sum(bin_sum) OVER w / sum(bin_ct) OVER w, 2) AS running_avg
FROM  (
   SELECT bin
        , sum(the_value) AS bin_sum
        , count(*)       AS bin_ct
   FROM   z
   WHERE  rn < 21   -- max 20 lowest values
   GROUP  BY 1
   ) sub
WINDOW w AS (ORDER BY bin)
ORDER  BY 1;

CTE y et z pourraient être confondus.De la même manière first et x pourraient être confondus.
Mais c'est plus clair ainsi.

Non testé, car nous n'avons pas de données de test.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top