2012-02-09 2 views
2

У меня есть куча Xs в базе данных MySQL. Некоторые Xs не идут вместе, и я хочу, чтобы таблица содержала все пары Xs и логическое значение, которое говорит, что они в порядке или нет.Можно ли выполнять параллельные поля в SQL?

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

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 

Сложность в обслуживании.

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

+0

В этом случае Xsub * x * является идентификатором, а не самими данными. Просто чтобы сделать эту часть понятной. –

+0

Возможно, вы сможете сортировать значения идентификаторов перед их просмотром. Тогда требуется только одна строка. –

ответ

6

магазин каждый действует группировка в виде таблицы, как это:

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 1 
FROM good_x 
WHERE x_id IN ([your list of values]) 
GROUP BY group_id 
HAVING count(1) = n; 
+0

Мне нравится, когда вы идете с этим, это напомнило мне то, что я забыл, MySQL может сделать, но у меня, вероятно, будет третья таблица, x_group, а затем ключ good_x от x_group.id. Мне это нравится. –

+0

Обратите внимание, как ваше решение позволяет хранить не только пары, но и группы произвольного размера. Может быть, 'pair_id' можно было бы переименовать :) – 9000

+0

Я думаю, что должен быть лучший способ, чтобы все самосоединившиеся, но не уверенные в себе. –

2

Я считаю, что вы можете использовать предложение 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") ; 

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

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

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

+0

Я надеюсь, что одни и те же базовые запросы будут работать с пятью x_ids, поэтому я считаю, что путь BD лучше. Но это полезный SQL, который мой случайный урок перескочил. Спасибо. –

0

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

Например, для пар «Xsub1» и «Xsub3» сохраните их в алфавитном порядке. Тогда при поиске для них, вы должны заказать их в алфавитном порядке в предложении WHERE как это:

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

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

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

+0

«Но что, если данные поступают в Xsub3, Xsub1?» Думаю, нам нужно больше узнать об этом процессе. –

+0

@BD, ваше решение лучше. Я отредактировал свой ответ, но любое приложение может изменить порядок параметров. :) –

+0

Я делаю это в другом месте. Разумный код для пар, но он не масштабируется. –

1

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

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) 

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

+0

Я вижу это. Просто эта сложность вытеснила таблицу SQL (которую я создал) нажимает на клиентское программное обеспечение (которое я написал), и я надеюсь, что в этом случае Фред Брукс ошибается и там * есть серебряная пуля. –

1

Хорошее решение зависит от характера отношений 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.

+0

в этом случае Xs являются кодами идентификаторов, которые я обычно устанавливаю как int (10). Я думаю, что я поеду на BD (я буду принимать код, когда у меня работает код), отчасти потому, что он более элегантно обрабатывает тройки, но мне никогда не приходило в голову использовать min() и max() в частях INSERT и WHERE запроса. Очень хаки, наилучшим образом. Спасибо. –

Смежные вопросы