Как проверить: Проверка связывания таблиц?

Ссылка скопирована
1 ответ

Сейчас ситуация такая: есть такие данные, вопрос, как не склеивая запрос из кусков определять следующий вариант,
Сейчас ситуация такая: если группа полностью включена или выключена, поле "is_uses", то данное условие не учитывается, если частично, то учитывается.

-- Таблица с данными CREATE TEMP TABLE IF NOT EXISTS _myTable( id SERIAL PRIMARY KEY , name text , param_0 int , param_1 int , param_2 int ); -- Таблица для хранения параметров фильтра CREATE TEMP TABLE IF NOT EXISTS _myFilter( id SERIAL PRIMARY KEY , index_param int , is_uses bool , _value int8 ); -- Заполняем таблицу с данными INSERT INTO _myTable(name, param_0, param_1, param_2) VALUES("test1_10_100", 1, 10 , 100); INSERT INTO _myTable(name, param_0, param_1, param_2) VALUES("test2_10_101", 2, 10 , 101); -- Заполняем таблицу фильтров INSERT INTO _myFilter(index_param, is_uses, _value) SELECT 0, True, DISTINCT param_0 FROM _myTable; INSERT INTO _myFilter(index_param, is_uses, _value) SELECT 1, True, DISTINCT param_1 FROM _myTable; INSERT INTO _myFilter(index_param, is_uses, _value) SELECT 2, True, DISTINCT param_2 FROM _myTable; -- Отключеем одно значение UPDATE _myFilter SET is_uses = False WHERE index_param = 0 AND _value = 1; --Получаем данные SELECT t.* FROM _myTable AS t WHERE t.param_0 IN (SELECT _value FROM _myFilter WHERE index_param = 0 AND is_uses) --<??? AND t.param_1 IN (SELECT _value FROM _myFilter WHERE index_param = 1 AND is_uses)--<??? AND t.param_2 IN (SELECT _value FROM _myFilter WHERE index_param = 2 AND is_uses)--<???
Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Web-разработка Ответ

В PostgreSQL для такой задачи не нужно склеивать SQL из кусков. Если фильтр частично включен, можно хранить условия в таблице и применять их через NOT EXISTS: “не существует активного условия, которому строка не соответствует”. Тогда отключенные группы просто не участвуют в фильтрации.

Сначала важное замечание: в PostgreSQL строки пишутся в одинарных кавычках, не в двойных. Тип string(10) тоже не используется, нужен text или varchar(10).

CREATE TEMP TABLE my_table(
  id serial PRIMARY KEY,
  name text,
  param_0 INT,
  param_1 INT,
  param_2 INT
);
 
CREATE TEMP TABLE my_filter(
  id serial PRIMARY KEY,
  index_param INT,
  is_uses BOOLEAN,
  VALUE INT
);

CREATE TEMP TABLE my_table( id serial PRIMARY KEY, name text, param_0 int, param_1 int, param_2 int ); CREATE TEMP TABLE my_filter( id serial PRIMARY KEY, index_param int, is_uses boolean, value int );

Если index_param указывает, какой столбец проверять, можно сделать CASE. Например, фильтр учитывается только когда is_uses = true:

SELECT t.*
FROM my_table t
WHERE NOT EXISTS (
  SELECT 1
  FROM my_filter f
  WHERE f.is_uses = TRUE
    AND (
      CASE f.index_param
        WHEN 0 THEN t.param_0
        WHEN 1 THEN t.param_1
        WHEN 2 THEN t.param_2
      END
    )  f.value
);

SELECT t.* FROM my_table t WHERE NOT EXISTS ( SELECT 1 FROM my_filter f WHERE f.is_uses = true AND ( CASE f.index_param WHEN 0 THEN t.param_0 WHEN 1 THEN t.param_1 WHEN 2 THEN t.param_2 END ) f.value );

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

SELECT t.*
FROM my_table t
WHERE NOT EXISTS (
  SELECT 1
  FROM (SELECT DISTINCT index_param FROM my_filter WHERE is_uses) g
  WHERE NOT EXISTS (
    SELECT 1
    FROM my_filter f
    WHERE f.is_uses
      AND f.index_param = g.index_param
      AND f.value = CASE g.index_param
        WHEN 0 THEN t.param_0
        WHEN 1 THEN t.param_1
        WHEN 2 THEN t.param_2
      END
  )
);

SELECT t.* FROM my_table t WHERE NOT EXISTS ( SELECT 1 FROM (SELECT DISTINCT index_param FROM my_filter WHERE is_uses) g WHERE NOT EXISTS ( SELECT 1 FROM my_filter f WHERE f.is_uses AND f.index_param = g.index_param AND f.value = CASE g.index_param WHEN 0 THEN t.param_0 WHEN 1 THEN t.param_1 WHEN 2 THEN t.param_2 END ) );

Временные таблицы в PostgreSQL есть, как и в MS SQL, создаются через CREATE TEMP TABLE. Они живут в рамках сессии и удобны для промежуточных расчетов. Но для фильтров часто достаточно CTE или обычных таблиц.

Практический вывод: используйте CASE + NOT EXISTS, а не динамический SQL. Если параметров станет много, нормализуйте данные: храните параметры строк в виде отдельной таблицы item_params(item_id, param_index, value). Тогда фильтрация станет проще и без CASE.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно