Учитывая две таблицы с неопределенным количеством строк с именем и значением, как бы я отобразил функцию поворота CROSS JOIN
над их значениями.
CREATE TEMP TABLE foo AS
SELECT x::text AS name, x::int
FROM generate_series(1,10) AS t(x);
CREATE TEMP TABLE bar AS
SELECT x::text AS name, x::int
FROM generate_series(1,5) AS t(x);
Например, если бы эта функция была умножением, как бы я сгенерировал (умножение) таблицу, как показано ниже,
Все эти (arg1,arg2,result)
строки могут быть сгенерированы с
SELECT foo.name AS arg1, bar.name AS arg2, foo.x*bar.x AS result
FROM foo
CROSS JOIN bar;
Так что это только вопрос представления, я хотел бы, чтобы это также работало с произвольным именем - именем, которое не просто является аргументом CAST
для текста, но установлено в таблице,
CREATE TEMP TABLE foo AS
SELECT chr(x+64) AS name, x::int
FROM generate_series(1,10) AS t(x);
CREATE TEMP TABLE bar AS
SELECT chr(x+72) AS name, x::int
FROM generate_series(1,5) AS t(x);
Я думаю, что это было бы легко выполнимо с CROSSTAB, способным к динамическому типу возврата.
SELECT * FROM crosstab(
'
SELECT foo.x AS arg1, bar.x AS arg2, foo.x*bar.x
FROM foo
CROSS JOIN bar
', 'SELECT DISTINCT name FROM bar'
) AS **MAGIC**
Но, без **MAGIC**
, я получаю
ERROR: a column definition list is required for functions returning "record" LINE 1: SELECT * FROM crosstab(
Для справки, используя приведенные выше примеры с именами , это нечто большее , как то , что tablefunc
«s crosstab()
хочет.
SELECT * FROM crosstab(
'
SELECT foo.x AS arg1, bar.x AS arg2, foo.x*bar.x
FROM foo
CROSS JOIN bar
'
) AS t(row int, i int, j int, k int, l int, m int);
Но теперь мы вернулись к предположениям о содержании и размере bar
таблицы в нашем примере. Так что если,
- Таблицы имеют неопределенную длину,
- Тогда перекрестное соединение представляет куб неопределенного измерения (из-за выше),
- Названия катагорий (на языке кросс-таблицы) приведены в таблице.
Что мы можем сделать лучше всего в PostgreSQL без «списка определений столбцов» для создания такого рода презентации?
источник
Ответы:
Простой случай, статический SQL
Нединамическое решение с
crosstab()
для простого случая:Я заказываю полученные столбцы
foo.name
, а неfoo.x
. И то и другое сортируется параллельно, но это простая установка. Выберите правильный порядок сортировки для вашего случая. Фактическое значение второго столбца не имеет значения в этом запросе (форма с 1 параметромcrosstab()
).Нам даже не нужно
crosstab()
с 2 параметрами, потому что по определению отсутствуют пропущенные значения. Видеть:(Вы исправили перекрестный запрос в вопросе, заменив
foo
сbar
в более поздней редакции. Это также фиксирует запрос, но продолжает работать с именами изfoo
.)Неизвестный тип возвращаемого значения, динамический SQL
Имена и типы столбцов не могут быть динамическими. SQL требует знать число, имена и типы результирующих столбцов во время вызова. Либо с помощью явного объявления, либо из информации в системных каталогах (вот что происходит
SELECT * FROM tbl
: Postgres ищет определение зарегистрированной таблицы.)Вы хотите, чтобы Postgres извлекал результирующие столбцы из данных в пользовательской таблице. Не произойдет.
Так или иначе, вам нужно две поездки туда и обратно на сервер. Либо вы создаете курсор, а затем проходите через него. Или вы создаете временную таблицу, а затем выбираете из нее. Или вы регистрируете тип и используете его в вызове.
Или вы просто генерируете запрос за один шаг и выполняете его в следующем:
Это генерирует запрос выше, динамически. Выполните это на следующем шаге.
Я использую Dollar-quotes (
$$
), чтобы упростить обработку вложенных кавычек. Видеть:quote_ident()
важно избежать в противном случае недопустимых имен столбцов (и, возможно, защитить от внедрения SQL).Связанный:
источник
Если вы представляете это как проблему презентации, вы можете рассмотреть возможность представления после запроса.
Более новые версии
psql
(9.6) идут с\crosstabview
показом результата в представлении кросс-таблицы без поддержки SQL (поскольку SQL не может произвести это напрямую, как упоминалось в ответе @ Эрвина: SQL требует знать число, имена и типы результирующих столбцов во время вызова )Например, ваш первый запрос дает:
Второй пример с именами столбцов ASCII дает:
См. Руководство по psql и https://wiki.postgresql.org/wiki/Crosstabview для получения дополнительной информации.
источник
Это не окончательное решение
Это мой лучший подход до сих пор. Еще нужно конвертировать окончательный массив в столбцы.
Сначала я получил декартово произведение обеих таблиц:
Но я добавил номер строки, чтобы идентифицировать каждую строку первой таблицы.
Тогда я получу результат в этом формате:
Преобразование его в строку, разделенную запятыми:
(Просто попробуйте позже: http://rextester.com/NBCYXA2183 )
источник
В качестве примечания, похоже, что SQL: 2016 будет учитывать это с помощью полиморфных табличных функций (ISO / IEC TR 19075-7: 2017)
Я нашел ссылку « Что нового в SQL: 2016», но автор не особо останавливается на этом.
источник