Выполнение агрегированного расчета внутри подгруппы - PullRequest
0 голосов
/ 27 февраля 2012

Я хочу вычислить 'внутри групповых квот using the bottom N` значений. Я прочитал несколько примеров здесь , которые объясняют множество различных способов вычисления этой меры, но я не полностью понимаю их (а некоторые не относятся к Postgresql). Я использую следующую таблицу для иллюстрации моего вопроса:

    a | b | x
   ---|---|------
    1 | 1 | 10.00
    1 | 2 | 15.00
    1 | 1 | 10.00
    1 | 2 | 15.00
    2 | 2 | 20.00
    2 | 1 | 21.00
    2 | 2 | 18.00

SQL для создания таблицы:

CREATE TABLE test(a int,b int,x decimal(6,2));
INSERT INTO test VALUES(1,1,10),(1,2,15), (1,1,10), (1,2,15), (2,2,20),(2,1,21),(2,2,18);

Я хочу иметь возможность рассчитать минимум самых низких значений N для группы. В этом примере я даю N = 2. Первый шаг, который я попробовал, следующий:

SELECT 
  t1.a,  
  AVG(t1.x) as avg_x
FROM 
  test AS t1
GROUP BY t1.a
ORDER BY avg_x

, который возвращает:

a | avg_x
--|------
1 | 12.50
2 | 19.66

То, что я пытался сделать (что дает неверный результат), это сделать подзапрос и ограничить количество результатов:

SELECT foo.* FROM 
(SELECT 
  t1.a,  
  AVG(t1.x) as avg_x
FROM 
  test AS t1
GROUP BY t1.a
ORDER BY avg_x
) as foo
ORDER BY foo.avg_x
LIMIT 2

Я знаю, что это не правильно, поскольку он не использует LIMIT для каждой подгруппы. Чтобы уточнить таблицу, которую я хочу вернуть:

a | avg_x
--|------
1 | 10.00
2 | 19.00

Необработанный результат для a=1 равен x = 10.0, 10.0, 21, со средним значением 10.0, 10.0.

Ответы [ 2 ]

1 голос
/ 27 февраля 2012
SELECT t1.a, round(AVG(t1.x), 2) as avg_x
FROM (SELECT * 
     FROM test t2
     WHERE x in (select x
                 from test t3
                 where t3.a = t2.a
                 order by x
                 limit 2)) as t1
GROUP BY t1.a
ORDER BY avg_x

Результат:

a | avg_x
--+-------
1 | 10.00
2 | 19.00

Если я правильно понял ваш вопрос.

1 голос
/ 27 февраля 2012

Я почти уверен, что это будет работать в PostgreSQL:

WITH T AS (
    SELECT A.*, ROW_NUMBER() OVER(PARTITION BY a ORDER BY x) AS rnk
    FROM @yourTable AS A
) 
SELECT a, AVG(x) avg_lowest_n_values
FROM T
WHERE rnk <= 2
GROUP BY a;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...