Значение SELECT в зависимости от имени базовой таблицы - PullRequest
2 голосов
/ 29 апреля 2020

Я хочу установить значение столбца на основе запрашиваемой таблицы.

Пример:

Предположим, две таблицы: Transportation и Locations. И оператор SELECT со столбцом с именем type, который должен содержать «Транспорт» или «Местоположения» в зависимости от запрашиваемой таблицы. Есть ли способ сделать это? Может быть, что-то похожее на «RegEx lookahead»?

Ответы [ 3 ]

2 голосов
/ 30 апреля 2020

tableoid - это путь к go, как уже предлагал Адам.

Но это быстрее и безопаснее:

SELECT CASE t.tableoid WHEN 'transportation'::regclass THEN 'Transportation'
                       WHEN 'locations'::regclass      THEN 'Locations'
                       ELSE 'Unknown' END AS type
FROM   some_table t;

Таким образом, мы приводим указанные таблицы к oid один раз - вместо двух приведений для каждой строки. Кроме того, сравнение OID (внутреннее 4-байтовое целое) обходится дешевле, чем text. Примерно в 10 раз быстрее в быстром тесте на Postgres 12.

Укажите имена таблиц, если возможна неоднозначность:

SELECT CASE t.tableoid WHEN 'public.transportation'::regclass THEN 'Transportation'
                       WHEN 'public.locations'::regclass      THEN 'Locations' ...

В противном случае вы зависите от текущего search_path из сеанс:

Если вы на самом деле используете смешанные имена, такие как правописание в вопросе предполагает, что вы должны добавить двойные кавычки:

SELECT CASE t.tableoid WHEN 'public."Transportation"'::regclass THEN 'Transportation'
                       WHEN 'public."Locations"'::regclass      THEN 'Locations' ...

См .:

Если указанные таблицы могут не существовать, вы рискуете получить ошибку от приведения. Вы можете предотвратить это, используя to_regclass() вместо:

SELECT CASE t.tableoid WHEN to_regclass('transportation') THEN 'Transportation'
                       WHEN to_regclass('locations')      THEN 'Locations' ...

Но эта функция дороже, чем обычное приведение. См .:

Ничто из этого не кажется на самом деле необходимым для ваш вариант использования. В любом случае вы должны адаптировать имя таблицы в предложении FROM, вы можете просто сделать то же самое для выражения в предложении SELECT.
Однако с наследованием или разбиением это может быть очень важно. См .:

1 голос
/ 29 апреля 2020

Используйте tableoid, приведение к regclass и затем к тексту.

testdb=# create table transportation(c text);
CREATE TABLE
testdb=# create table locations(c text);
CREATE TABLE
testdb=# insert into transportation select 'foo';
INSERT 0 1
testdb=# insert into locations select 'bar';
INSERT 0 1
testdb=# select c, CASE WHEN tableoid::regclass::text='transportation' then 'Transportation' when tableoid::regclass::text='locations' then 'Locations' else 'Unknown' end as "type" from locations /* transportation */;
  c  |   type    
-----+-----------
 bar | Locations
(1 row)

testdb=# select c, CASE WHEN tableoid::regclass::text='transportation' then 'Transportation' when tableoid::regclass::text='locations' then 'Locations' else 'Unknown' end as "type" from /*locations */ transportation ;
  c  |      type      
-----+----------------
 foo | Transportation
(1 row)

Больше информации о tableoid .

0 голосов
/ 29 апреля 2020

Обычно это обрабатывается через left join с, с разумным использованием coalesce():

select o.*, coalesce(t.name, l.name) as name
from originaltable o left join
     transportation t
     on t.transportation_id = o.combined_id and o.type = 'T' left join
     locations l
     on l.location_id = o.combined_id and o.type = 'L'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...