2016-04-18 3 views
3

У меня есть postgresql db с таблицей t1, и я хочу рассчитать порог. порог должен быть, например, автомобиль 1 использует больше топлива, чем 75% всех автомобилей, car2 использует больше топлива, чем 50% всех автомобилей, .... математически я понимаю, что я хочу делать, но я не знаю, как построить запросPostgreSQL вычисляет пороговый запрос

id | name | value | threshold 
________________________ 

1 | car1 | 30 | ...% 
2 | car2 | 15 | ..% 
3 | car3 | 7 | 
4 | car4 | 5 | 

вот SQL FIDDLE http://sqlfiddle.com/#!15/1e914/1

UPDATE t1 
SET threshold = 
    select count(value) 
    from t1 

где (значение> [над каждой строки]) и затем * 100/общее кол-()

извините за эту неудачную попытку, но я потерял. также попробовал некоторые совокупные функции.

+1

Посмотрите на '100 * PERCENT_RANK() OVER (ORDER BY значения) или' 100 * CUME_DIST() OVER (ORDER BY значения) ' – dnoeth

+0

@dnoeth Оба они не работают, так как решение по сравнению с самым экономичным автомобилем и не рассчитан по всему населению. – Patrick

+1

@Patrick: Если эти функции не работают, ваш ответ также неверен. Оба являются лишь небольшими вариациями вашего 'RANK/COUNT' :-) – dnoeth

ответ

5

Вы можете решить эту проблему весьма элегантно с window function:

UPDATE t1 
SET threshold = sub.thr 
FROM (
    SELECT id, 100. * (rank() OVER (ORDER BY value) - 1)/count(*) OVER() AS thr 
    FROM t1) sub 
WHERE t1.id = sub.id; 

rank() функция дает ранг (начиная с 1) в упорядоченном множестве, в данном случае через колонку value, которая затем делится на общее количество строк в наборе. Заметим, что вычисляет общее количество строк в разделе, но оно не объединяет строки, как обычный count(*).

+0

Спасибо всем за помощь. на ссылке sqlfiddle выше вы можете увидеть различия между rank(), percent_rank(), cume_dist(). Я думаю, что искал процент. я изменил порядок, теперь я могу сказать, что 33% автомобилей используют больше топлива, чем автомобиль2. (кстати, мой реальный стол не о машинах). одна вещь для добавления, оконные функции не работают с UPDATE – fabvys

+0

Вы можете обернуть функции окна в подвыборку, а затем он должен работать. См. Обновленный ответ. Обратите внимание, что использование 'percent_rank()' дает результат, отличный от того, что вы указываете в своем вопросе. Там процент относится к наиболее экономичному автомобилю, а функция вычисляет все строки. '(rank() - 1)/count (*)' дает точно результат, о котором вы просили. – Patrick

+0

true, (rank() ... является правильной функцией, которая работает на мой вопрос. Еще раз спасибо. – fabvys

0

Вы хотите рассчитать процент потребления топлива?

UPDATE t1 
SET threshold = 
    (select value * 100/t2.sumValue 
    from (select sum(value) sumValue from t1) t2 
    ) 

Или, если вы хотите рассчитать определенный порог, можете ли вы показать ожидаемый результат?

1
WITH q AS 
     (
     SELECT *, 
       (RANK() OVER (ORDER BY value) - 1) * 100./COUNT(*) OVER() nt 
     FROM mytable 
     ) 
UPDATE mytable 
SET  threshold = nt 
FROM q 
WHERE mytable.id = q.id 
+0

спасибо, это работает. – fabvys