Intereting Posts
SQL-запрос, который сообщает N или более последовательных отсутствий из таблицы посещаемости Выполните этот запрос рабочих часов в PostgreSQL Как запустить пакетный файл из процедуры PL / SQL Учет запроса занимает много времени F #: Как создать рамку Deedle с источником данных SQL Проблема с запросом Oracle (пространственная геометрия) Как выбрать последние две записи для каждого topic_id в MySQL Простой запрос SQL Select для обхода всех подключенных людей в социальном графе? Как лучше блокировать несколько «счетчиков» на счетчике? Возврат соответствующей даты из нескольких таблиц, включая дополнительную информацию о таблице Как преобразовать двоичную строку обратно в Byte в CSharp. Hex-номер, созданный SQL Server 2012 Varbinary (8) Подготовленный оператор с динамическим предложением where Поиск массива SQL Сравнение шаблонов SQL Как вы находите результаты, которые произошли на прошлой неделе?

Можно ли назвать столбцы результатов SQL из строк в другой таблице? (Postgres)

В основном у меня есть пользователи с динамической таблицей атрибутов. Упрощенная:

SELECT * FROM users; id | email -----+------------------------------------------ 1 | example@example.com SELECT * FROM user_attributes; id | name ----+---------------- 1 | Salutation 2 | Given Name 3 | Surname 4 | Alias 5 | Address 6 | Address 2 7 | Address 3 8 | City 9 | Region .... SELECT * FROM user_attribute_values; client_id | attribute_id | value -----------+--------------+------- 

То, что я ищу, – это SELECT, который будет возвращать столбцы user_id, city, region, где город и регион не пусты.

Причиной таблицы user_attributes может быть желание сохранить любое количество настраиваемых полей для пользователя, и невозможно заранее знать, каким образом они будут создавать их в виде столбцов таблицы пользователя.

Используйте INNER JOIN для этого:

 SELECT u.id, a_city.value AS city, a_region.value AS region FROM users u INNER JOIN user_attribute_values a_city ON a_city.client_id = u.id AND a_city.attribute_id = 8 INNER JOIN user_attribute_values a_region ON a_region.client_id = u.id AND a_region.attribute_id = 9 WHERE LENGTH(a_city.value) > 0 AND LENGTH(a_region.value) > 0 

Это основано на принципиальном непонимании внутренней работы конструкций Postgres и EAV .

Если у вас нет сотен разных полей или динамического набора типов атрибутов, используйте единую таблицу со всеми столбцами – кроме нормализации базы данных . Столбцы без значения заполняются NULL .
Нулевое хранение очень дешево .

  • 1 бит на столбец в таблице для нулевой битовой карты, обычно выделяемой в единицах 8 байтов, которая охватывает 64 столбца.
  • Отдельная строка для одного дополнительного атрибута занимает как минимум 28 байтов .

     4 bytes item pointer 23 bytes heap tuple header 1 byte padding 

    Обычно больше, из-за заполнения и дополнительных накладных расходов.

Там должны были быть сотни различных, малонаселенных столбцов, прежде чем такой громоздкий дизайн EAV мог бы заплатить – и hstore или jsonb в Postgres 9.4 были бы превосходными решениями для этого . Между вашим дизайном почти нет места, и если бы это было так, вы бы, вероятно, использовали enum для этого типа.

В то же время запросы сложнее и дороже. Мы находимся в узком месте.

Вместо этого используйте раскладку таблицы следующим образом:

 CREATE TABLE users ( users_id serial PRIMARY KEY , salutation text , given_name text , surname text , alias text ... (many) more columns ); CREATE TABLE address ( address_id serial PRIMARY KEY , users_id int REFERENCES users , city text -- or separate TABLE city incl region_id etc. ... , region_id int REFERENCES region , address text ... (many) more columns ); 

Близкий ответ с дополнительными советами:

  • SQL: создать полную запись из 2 таблиц
 select client_id, min(case when attribute_id = 8 then value else '0' end) as city, min(case when attribute_id = 9 then value else '0' end) as region from user_attribute_values group by clientid having min(case when attribute_id = 8 then value else '0' end) <> '0' or min(case when attribute_id = 9 then value else '0' end) <> '0' 

Это покажет клиентам стоимость города или региона. Если вы хотите, чтобы только клиенты с BOTH такими атрибутами, в условии наличия, измените OR на AND.