MySQL:如何改进这个联盟?
我有两个表,a用于访问,p用于提供程序。然后我有第三个表,用于将这些表连接在一起,即标准规范化。但是,提供程序表是一个父/子表,联接表可以选择是否应为所有提供程序子级授予访问权限MySQL:如何改进这个联盟?,mysql,sql,Mysql,Sql,我有两个表,a用于访问,p用于提供程序。然后我有第三个表,用于将这些表连接在一起,即标准规范化。但是,提供程序表是一个父/子表,联接表可以选择是否应为所有提供程序子级授予访问权限 CREATE TABLE p ( p_id int PRIMARY KEY, name varchar(32), parent_id int, FOREIGN KEY (parent_id) REFERENCES p(p_id) ); CREATE TABLE a ( a_id
CREATE TABLE p (
p_id int PRIMARY KEY,
name varchar(32),
parent_id int,
FOREIGN KEY (parent_id) REFERENCES p(p_id)
);
CREATE TABLE a (
a_id int PRIMARY KEY,
name varchar(32)
);
CREATE TABLE ap (
a_id int,
p_id int,
sub tinyint,
FOREIGN KEY (a_id) REFERENCES a(a_id),
FOREIGN KEY (p_id) REFERENCES p(p_id)
);
一些示例数据,1个提供程序和2个子提供程序。2个访问用户,1个无子访问,1个有子访问
INSERT INTO p VALUES(1, 'a', null);
INSERT INTO p VALUES(2, 'a.a', 1);
INSERT INTO p VALUES(3, 'a.b', 1);
INSERT INTO a VALUES(1, 'user 1');
INSERT INTO a VALUES(2, 'user 2');
INSERT INTO ap VALUES(1, 1, 0);
INSERT INTO ap VALUES(2, 1, 1);
结果是,我希望根据第三个表获得用户有权访问的提供者列表
目前,我通过使用UNION连接两个查询来解决这个问题。第一个查询选择可能的子提供者,第二个查询选择主提供者
SELECT p_id, name
FROM p
WHERE parent_id IN(
SELECT p_id FROM ap WHERE a_id = 1 AND sub = 1
)
UNION
SELECT ap.p_id, p.name
FROM ap
LEFT JOIN p ON p.p_id = ap.p_id
WHERE a_id = 1;
我不喜欢这个查询,它很难看,必须有一个更聪明的方法:)如果我的逻辑正确,那么您需要
p
中的所有记录,其中以下一项为真:
为给定的p\u id
匹配a\u id
中的记录ap
为给定的parent\u id
匹配a\u id
中的记录ap
exists
:
select p.p_id, p.name
from p
where exists (select 1
from ap
where ap.p_id = p.p_id and ap.a_id = 1
) or
exists (select 1
from ap
where ap.p_id = p.parent_id and ap.sub = 1 and ap.a_id = 1
)
在
ap(p\id,a\id,sub)
上有一个复合索引,这应该比您的查询版本有更好的性能。如果您没有问题(即一切正常),这个问题可能更适合新用户的第一个问题,谢谢,这真的做得很好。我们有所有需要设置和测试的内容。您是否想要一个提供者,在父/子层次结构中,其父/子层次结构中的哪一个与用户(a)有关系?如果您提供一些完全匹配的示例数据和所需的输出,则会更好。因此,这里为您提供小提琴:,但您预期的结果是什么?谢谢,这看起来比我原来的查询好多了。