PostgreSQL: Таблица плавления и вычисление процентного содержания для разных групп - PullRequest
1 голос
/ 21 июня 2020

Я пытаюсь создать воронкообразную диаграмму, но сейчас мои данные находятся в широком формате. В нем есть пара групп, которые я хочу сравнить (например, A и B в приведенном ниже примере), и они находятся в разных масштабах, поэтому я хочу использовать пропорции, а также необработанные значения.

У меня есть начальная таблица, которая выглядит так:

| group | One | Two | Three |
|-------|-----|-----|-------|
|  A    | 100 | 75  | 50    |
|  B    | 10  | 7   | 6     |
|-------|-----|-----|-------|

Мне нужно, чтобы таблица выглядела так:

| group | stage | count | proportion of stage One |
|-------|-------|-------|-------------------------|
|  A    | One   | 100   | 1                       |
|  A    | Two   | 75    | 0.75                    |
|  A    | Three | 50    | 0.5                     |
|  B    | One   | 10    | 1                       |
|  B    | Two   | 7     | 0.7                     |
|  B    | Three | 6     | 0.6                     |
|-------|-------|-------|-------------------------|

Пропорция рассчитывается как значение каждой строки, деленное на максимальное значение для этой группы. На первом этапе всегда будет 100%, затем на втором этапе - это count для этой строки, деленное на максимальное значение count для этого значения группы.

Лучшее, что я мог сделать, это подключиться к базе данных в python и используйте Pandas, чтобы растопить стол, но я бы очень хотел сохранить все в сценарии SQL.

Я возился и добился нулевого прогресса на четыре слишком долго. Любая помощь приветствуется.

Ответы [ 2 ]

2 голосов
/ 21 июня 2020

Вы можете сделать это с помощью запроса UNION, выбрав сначала значения One, затем Two и Three с соответствующим делением, чтобы получить пропорцию:

SELECT "group", 'One' AS stage, One, 1 AS proportion
FROM data
UNION ALL
SELECT "group", 'Two', Two, ROUND(1.0*Two/One, 2)
FROM data
UNION ALL
SELECT "group", 'Three', Three, ROUND(1.0*Three/One, 2)
FROM data
ORDER BY "group"

Вывод :

group   stage   one     proportion
A       One     100     1
A       Two     75      0.75
A       Three   50      0.50
B       One     10      1
B       Two     7       0.70
B       Three   6       0.60

Демонстрация на dbfiddle

1 голос
/ 21 июня 2020

Я бы порекомендовал боковое соединение:

SELECT t."group", v.stage, v.count, v.count * 1.0 / t.one
FROM t CROSS JOIN LATERAL
     (VALUES ('One', one),
             ('Two', two),
             ('Three', three)
     ) v(stage, count);

Боковое соединение должно быть немного быстрее, чем union all на небольшом объеме данных. По мере того, как данные становятся больше, только одно сканирование таблицы является большим выигрышем. Однако самый большой выигрыш - когда «таблица» действительно представляет собой более сложный запрос. Тогда производительность бокового соединения может быть значительно выше.

...