Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL:如何改进这个联盟?_Mysql_Sql - Fatal编程技术网

MySQL:如何改进这个联盟?

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

我有两个表,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 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)有关系?如果您提供一些完全匹配的示例数据和所需的输出,则会更好。因此,这里为您提供小提琴:,但您预期的结果是什么?谢谢,这看起来比我原来的查询好多了。