Использование ARRAY для решения проблемы с составным ключом
Я думаю, что реальная проблема, с которой вы столкнулись, заключается в том, что ваш sub_location
является частью вашего основного идентификатора (имени) для целей кросса. И не то, что кросс-таблица вызывает дополнительный столбец.
Ожидается, что «дополнительные» столбцы будут одинаковыми для всех строк с одинаковым значением row_name.
Таким образом, составные ключи, образующие имя, должны сериализоваться пользователем. Вы все еще можете выполнить эту работу, сериализуя в SQL ARRAY
типа text[]
, используя ARRAY[location, sub_location]::text[]
.
SELECT *
FROM crosstab(
$$ SELECT ARRAY[location, sub_location]::text[], step, amount FROM loc ORDER BY 1, 2, 3; $$,
$$ SELECT DISTINCT step FROM loc ORDER BY 1; $$
) AS t(location text[], step_1 int, step_2 int, step_3 int );
location | step_1 | step_2 | step_3
-------------+--------+--------+--------
{100,100_A} | 2 | 7 | 6
{100,100_B} | 5 | 8 | 9
(2 rows)
Использование вашей подлокации с фактической локацией в ней
Теперь, поскольку подлокация в вашем конкретном случае содержит данные о местоположении, мы можем сделать это еще короче, изменив порядок. Я бы не стал хранить подместоположение в таблице с 100_
, но мы можем использовать это здесь. Чтобы было ясно, это не сработает, если location: 100, sublocation: 'A'
так я бы его сохранил.
SELECT *
FROM crosstab(
$$ SELECT sub_location, location, step, amount FROM loc ORDER BY 1, 2, 3; $$,
$$ SELECT DISTINCT step FROM loc ORDER BY 1; $$
) AS t(sub_location text, location int, step_1 int, step_2 int, step_3 int );
sub_location | location | step_1 | step_2 | step_3
--------------+----------+--------+--------+--------
100_A | 100 | 2 | 7 | 6
100_B | 100 | 5 | 8 | 9
(2 rows)
Однако это устраняет сложность вызова ARRAY
.
Упрощение для вашего варианта использования
Мы также можем просто отбросить `местоположение в этот момент или изменить порядок в родительском запросе.
SELECT *
FROM crosstab(
$$ SELECT sub_location, step, amount FROM loc ORDER BY 1, 2, 3; $$,
$$ SELECT DISTINCT step FROM loc ORDER BY 1; $$
) AS t(location_full text, step_1 int, step_2 int, step_3 int );
location_full | step_1 | step_2 | step_3
---------------+--------+--------+--------
100_A | 2 | 7 | 6
100_B | 5 | 8 | 9
(2 rows)
Не уверен, какой метод выше работает лучше всего для вас. Не забудьте CREATE EXTENSION tablefunc;
Конечно, это абсолютно субъективно, легче ли это, чем версия без перекрестных таблиц.
person
Evan Carroll
schedule
14.04.2017