Могу ли я сделать параллельные поля в SQL? - PullRequest
2 голосов
/ 09 февраля 2012

У меня есть куча X в базе данных MySQL. Некоторые X не сочетаются друг с другом, и я хочу таблицу, в которой хранятся все пары X, и логическое значение, показывающее, в порядке они или нет.

Эта часть достаточно проста:

CREATE TABLE good_x (
    X_id_1 int(10) not null ,
    X_id_2 int(10) not null ,
    is_good tinyint(1) 
    ) ;

Мой вопрос таков: учитывая, что Xsub1 и Xsub3 идут вместе.

SELECT is_good from good_x where X_id_1 = "Xsub1" and X_id_2 = "Xsub3" ;

Но что, если данные поступят в Xsub3, Xsub1? Я мог бы иметь две записи в таблице:

Xsub1,Xsub3,1
Xsub3,Xsub1,1

Но тогда вы должны отслеживать две вещи. В моем случае это контролируемый словарный запас, поэтому я не ожидаю больших изменений. Но если я захочу добавить третий X, Xsub5, вы получите шесть записей, с которыми нужно связываться.

Xsub1,Xsub3,Xsub5,1
Xsub1,Xsub5,Xsub3,1
Xsub3,Xsub1,Xsub5,1
Xsub3,Xsub5,Xsub1,1
Xsub5,Xsub1,Xsub3,1
Xsub5,Xsub3,Xsub1,1

Что трудно поддерживать.

Есть ли способ, которым я могу добавить группу X, два или более, и связать это с логическим значением, поэтому мне не нужно иметь отдельные таблицы для двойников, троек, четырехугольников, квинт и т. Д. возможно в любом SQL, и если да, то каков синтаксис?

Ответы [ 5 ]

6 голосов
/ 09 февраля 2012

Храните каждую допустимую группу в таблице следующим образом:

CREATE TABLE good_x (x_id CHAR, group_id INT);

Поместите его в группы, подобные этой:

INSERT INTO good_x(x_id,group_id) values ('Xsub3',1);
INSERT INTO good_x(x_id,group_id) values ('Xsub1',1);

и для 3:

INSERT INTO good_x(x_id,group_id) values ('Xsub3',2);
INSERT INTO good_x(x_id,group_id) values ('Xsub1',2);
INSERT INTO good_x(x_id,group_id) values ('Xsub5',2);

Теперь запустите SELECT следующим образом:

SELECT 1
FROM   good_x
WHERE  x_id IN ([your list of values])
GROUP BY group_id
HAVING count(1) = n;
2 голосов
/ 09 февраля 2012

Полагаю, вы могли бы использовать предложение IN.

SELECT is_good 
  from good_x 
 where X_id_1 in ("Xsub1","Xsub3","Xsub5")
   and X_id_2 in ("Xsub1","Xsub3","Xsub5") 
   and X_id_3 in ("Xsub1","Xsub3","Xsub5") ; 

И если вам не нужны одинаковые значения в разных столбцах, вы можете добавить

   and ( X_id_1 <> X_id_2
   and   X_id_1 <> X_id_3
   and   X_id_2 <> X_id_3 )

Это, изКонечно, не будет идеальным, если у вас слишком много столбцов или разные значения.

1 голос
/ 09 февраля 2012

Хорошее решение немного зависит от характера отношения is_good и значений X.

Если значения X можно упорядочить, то вы можете использовать упорядочение для сохранения парных отношений только с одной записью, а не двумя. Просто сохраняйте min(x1, x2) в x_id_1 и max(x1, x2) в x_id_2 всякий раз, когда вы вставляете. Затем используйте тот же подход при запросе пар: select ... where x_id_1 = min(x_sub_1, x_sub_2) and x_id_2 = max(x_sub_1, x_sub_2).

Если отношение is_good является симметричным и транзитивным, и если существует довольно маленький и стабильный набор значений X, то альтернативным подходом может быть использование побитовой логики. Каждый бит представляет отдельное значение X, и каждая запись в таблице содержит битовую комбинацию, которая обозначает, что все биты X со значением «1» находятся в отношениях is_good друг с другом. Запросы просто включают поиск записи с установленными правильными битами: select ... where x_bitfield & my_query_bitfield = my_query_bitfield.

1 голос
/ 09 февраля 2012

Если вы как-то упорядочите свои X (например, по их числовому искусственному ПК), вам нужно будет хранить только один набор X, а не все перестановки.Это стоило бы заказа X перед запросом.

OTOH список запросов «что X совместимо с» станет дороже (вам понадобится 2 индекса и 2 запроса).

Вы можете использовать полностью общее решение, например:

create table compatible (
  group_id number not null,
  x_id number foreign key references x(id),
  primary key (group_id, x_id)
);
create unique index ... on compatible(x_id, group_id)

Чтобы сохранить тот факт, что любое число X совместимо, вы создаете столько записей в таблице compatible с одинаковым произвольным значением group_id.Вы можете эффективно определить, совместимы ли некоторые элементы, запросив их group_id s и проверив, совпадают ли они (используйте exists).Вы можете эффективно найти все вещи, которые совместимы с конкретным X. Вы не ограничены размером группы совместимых элементов и никогда не заботитесь о перестановках.

0 голосов
/ 09 февраля 2012

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

Например, для пар «Xsub1» и «Xsub3» сохраняйте их в алфавитном порядке. Затем при их поиске вы должны упорядочить их в алфавитном порядке в предложении WHERE, например:

SELECT * FROM
good_x
WHERE x_id_1 = 'Xsub1'
AND x_id_2 = 'Xsub3'

Это позволит избежать дубликатов и потребует только минимальной предварительной обработки.

Я думаю, что решение BD лучше, если вы не возражаете против редизайна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...