我在MySQL数据库中有一堆X.有些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中都可以,如果是,那么语法是什么?
答案 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:
SELECT 1
FROM good_x
WHERE x_id IN ([your list of values])
GROUP BY group_id
HAVING count(1) = n;
答案 1 :(得分: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") ;
如果您不希望在不同的列中使用相同的值,则可以添加
and ( X_id_1 <> X_id_2
and X_id_1 <> X_id_3
and X_id_2 <> X_id_3 )
当你有太多列或不同的值时,这当然不太理想。
答案 2 :(得分:1)
如果你以某种方式订购你的Xs(例如通过他们的数字人工PK),你只需要存储一组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
并检查它们是否匹配(使用exists
)。您可以有效地查找与特定X兼容的所有内容。您不受兼容项组的大小限制,也不关心排列。
答案 3 :(得分: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值,并且表中的每个记录包含一个位模式,表示具有“1”值的所有X位彼此处于is_good
关系。查询只需要找到设置了适当位的记录:select ... where x_bitfield & my_query_bitfield = my_query_bitfield
。
答案 4 :(得分:0)
使用当前设计的最简单的解决方案是确保在将它们存储在数据库中的对中时,按顺序存储它们。
例如,对于'Xsub1'和'Xsub3'对,按字母顺序存储它们。然后在搜索它们时,您必须在WHERE
子句中按字母顺序对它们进行排序,如下所示:
SELECT * FROM
good_x
WHERE x_id_1 = 'Xsub1'
AND x_id_2 = 'Xsub3'
这样可以避免重复,只需要进行最少量的预处理。
如果您不介意重新设计,我认为BD的解决方案会更好。