2016-03-24 1 views
3

У меня есть TABLE_A, и мне нужно создать TABLE_A_FINAL.

Правило:
В TABLE_A_FINAL у нас есть строки со всеми возможными комбинациями ID_C, а если в TABLE_A такая же комбинация ID_C, мы умножаем значение WEIGHT.
Возможно ли это в SQL? Спасибо за помощь и советы.Анализ таблицы в SQL (умножение)

TABLE_A
ID_N |WEIGHT |ID_C | 1 |1.15 | 1A | 2 |1.13 | 1A | 3 |1.65 | 1B | 4 |1.85 | 2A | 6 |1.57 | 2A |


TABLE_A_FINAL
ID_C |FINAL_WEIGHT | 1A |1.15×1.13 = 1.2995 | 1B |1.65 | 2A |1.85×1.57 = 2.9045 |

+1

[здесь] (http://stackoverflow.com/a/21623421/593144) с некоторыми исправлениями: 'CREATE AGGREGATE MUL (числовой) (SFUNC = numeric_mul, STYPE = числовой); ' – Abelisto

ответ

3

К сожалению, Postgres не имеет функции в product() агрегации. Эту функцию можно эмулировать с помощью sum() и log/exponentiation. Поскольку все ваши ценности кажутся положительными и ненулевым:

select id_c, exp(sum(ln(weight)) as final_weight 
from table_a 
group by id_c; 

Если у вас есть нули или отрицательные числа, то логика несколько сложнее, но все же вполне возможно.

2

Рекурсивный CTE над окном для обнаружения цепи диапазонов последовательных id_c:

WITH RECURSIVE yy AS (
     WITH xx AS (
       SELECT id_n,weight,id_c 
       , lead(id_n) over (PARTITION BY id_c ORDER BY id_n) AS nxt 
       , rank() over (PARTITION BY id_c ORDER BY id_n) rnk 
       FROM multipliers 
       ) 
     SELECT x0.rnk, x0.id_n,x0.weight,x0.id_c , x0.nxt 
       , x0.weight AS prod 
     FROM xx x0 
     WHERE x0.rnk = 1 -- START of a chain 
     UNION ALL 
     SELECT x1.rnk, x1.id_n,x1.weight,x1.id_c , x1.nxt 
       , yy.prod * x1.weight AS prod 
     FROM xx x1 
     JOIN yy ON x1.id_c = yy.id_c 
      AND x1.rnk = 1+ yy.rnk -- NEXT member of chain 
     ) 
SELECT * FROM yy 
WHERE yy.nxt IS NULL -- no next: this must be the END of a chain 
     ; 

Если есть нулевые или отрицательные веса, это будет по-прежнему ведут себя, как ожидалось. NULL значения веса может лечиться yy.prod * AS COALESCE(x.weight,1) AS prod и т.д.

+0

благодарит вас за помощь :-) – hanznv

+0

@hanznv. , , Я удивлен, что вы приняли этот ответ. Хотя это правильно, оно, вероятно, будет намного медленнее, чем решение для агрегации. –

+0

@GordonLinoff: но это числовое значение. Версия exp/ln может пострадать от ошибок округления. – joop

Смежные вопросы