查找员工用户有权访问的最快方法是什么?

ash*_*ram 5 sql oracle

我有一张员工表,其中包含一般员工信息.另一个包含用户信息的User表.用户可以创建员工.

当用户创建员工时,用户将部门,产品,子产品和区域分配给员工.

用户他们可以访问特定的部门,产品,子产品和区域.

例如,用户A可以访问D1部门,产品P1(地区=亚洲,美国),P2(地区=亚洲),P3(地区=亚洲,美国).

Division是Product的父级.每个部门都可以有很多产品.

当我说用户A可以访问产品P1(地区=亚洲,美国)时,这意味着用户A可以添加产品= P1和地区=亚洲或美国的员工.

他不能将员工添加到产品P1或任何其他产品本身的任何其他区域.

如果假设用户A在db中添加了500名员工,则另一个用户B已添加500名其他员工,依此类推.

如何编写有效的查询以获取我可以访问的员工?

请注意,可能会发生另一个具有相同访问权限的用户可以添加员工,我也应该能够看到这些员工.

下面是我的db模式.

        --------------------------------------------------------
    --  DDL for Table BI_DIVISION
    --------------------------------------------------------

      CREATE TABLE "HEADCOUNT_BI"."BI_DIVISION" 
       (    "DIVISION_ID" NUMBER(*,0) NOT NULL 
        "DIVISION_NAME" VARCHAR2(4000) 
       ) ;

    --------------------------------------------------------
    --  DDL for Table BI_PRODUCT
    --------------------------------------------------------

      CREATE TABLE "HEADCOUNT_BI"."BI_PRODUCT" 
       (    "PRODUCT_ID" NUMBER(*,0) NOT NULL , 
        "PRODUCT_NAME" VARCHAR2(4000), 
        "DIVISION_ID" NUMBER(*,0) 
       ) ;


    --------------------------------------------------------
    --  DDL for Table BI_SUB_PRODUCT
    --------------------------------------------------------

      CREATE TABLE "HEADCOUNT_BI"."BI_SUB_PRODUCT" 
       (    "SUB_PRODUCT_ID" NUMBER(*,0) NOT NULL, 
        "SUB_PRODUCT_NAME" VARCHAR2(4000), 
        "PRODUCT_ID" NUMBER(*,0), 
       ) ;


    --------------------------------------------------------
    --  DDL for Table BI_REGION
    --------------------------------------------------------

      CREATE TABLE "HEADCOUNT_BI"."BI_REGION" 
       (    "REGION_ID" NUMBER(*,0) NOT NULL, 
        "REGION_NAME" VARCHAR2(4000) NOT NULL ENABLE 
       ) ;


    --------------------------------------------------------
    --  DDL for Table BI_EMPLOYEE
    --------------------------------------------------------

      CREATE TABLE "HEADCOUNT_BI"."BI_EMPLOYEE" 
       (    "EMP_ID" NUMBER(*,0) NOT NULL , 
        "DIVISION_ID" NUMBER(*,0), 
        "PRODUCT_ID" NUMBER(*,0), 
        "SUB_PRODUCT_ID" NUMBER(*,0), 
        "REGION_ID" NUMBER(*,0) ,
        "CONFIDENTIAL" VARCHAR2(1) DEFAULT 'Y' 
       );


    --------------------------------------------------------
    --  DDL for Table BI_USER
    --------------------------------------------------------

      CREATE TABLE "HEADCOUNT_BI"."BI_USER" 
       (    "USER_ID" NUMBER(*,0) NOT NULL, 
        "FIRSTNAME" VARCHAR2(4000), 
        "LASTNAME" VARCHAR2(4000) 
       ) ;


    --------------------------------------------------------
    --  DDL for Table BI_USER_ACCESS
    --------------------------------------------------------

      CREATE TABLE "HEADCOUNT_BI"."BI_USER_ACCESS" 
       (    "USER_ACCESS_ID" NUMBER(*,0) NOT NULL, 
        "USER_ID" NUMBER(*,0), 
        "DIVISION_ID" NUMBER(*,0), 
        "PRODUCT_ID" NUMBER(*,0), 
        "SUB_PRODUCT_ID" NUMBER(*,0), 
        "REGION_ID" NUMBER(*,0), 
        "ACCESS_LEVEL" NUMBER(*,0), 
        "CONFIDENTIAL" VARCHAR2(1) DEFAULT 'Y' 
       ) ;

    Insert into BI_DIVISION (DIVISION_ID,DIVISION_NAME) values (1,'DIVISION 1');
    Insert into BI_DIVISION (DIVISION_ID,DIVISION_NAME) values (2,'DIVISION 2');

    Insert into BI_PRODUCT (PRODUCT_NAME,DIVISION_ID,PRODUCT_ID) values ('PRODUCT 1',1,1);
    Insert into BI_PRODUCT (PRODUCT_NAME,DIVISION_ID,PRODUCT_ID) values ('PRODUCT 2',1,2);
    Insert into BI_PRODUCT (PRODUCT_NAME,DIVISION_ID,PRODUCT_ID) values ('PRODUCT 3',2,3);
    Insert into BI_PRODUCT (PRODUCT_NAME,DIVISION_ID,PRODUCT_ID) values ('PRODUCT 4',2,4);

    Insert into BI_SUB_PRODUCT (SUB_PRODUCT_ID,SUB_PRODUCT_NAME,PRODUCT_ID) values (1,'SUB PRODUCT 1', 1);
    Insert into BI_SUB_PRODUCT (SUB_PRODUCT_ID,SUB_PRODUCT_NAME,PRODUCT_ID) values (2,'SUB PRODUCT 2', 1);
    Insert into BI_SUB_PRODUCT (SUB_PRODUCT_ID,SUB_PRODUCT_NAME,PRODUCT_ID) values (3,'SUB PRODUCT 3', 2);
    Insert into BI_SUB_PRODUCT (SUB_PRODUCT_ID,SUB_PRODUCT_NAME,PRODUCT_ID) values (4,'SUB PRODUCT 4', 2);
    Insert into BI_SUB_PRODUCT (SUB_PRODUCT_ID,SUB_PRODUCT_NAME,PRODUCT_ID) values (5,'SUB PRODUCT 5', 3);


    Insert into BI_REGION (REGION_ID,REGION_NAME) values (1,'Americas');
    Insert into BI_REGION (REGION_ID,REGION_NAME) values (2,'Asia');
    Insert into BI_REGION (REGION_ID,REGION_NAME) values (3,'Germany');
    Insert into BI_REGION (REGION_ID,REGION_NAME) values (4,'Japan');
    Insert into BI_REGION (REGION_ID,REGION_NAME) values (5,'Pacific');
    Insert into BI_REGION (REGION_ID,REGION_NAME) values (6,'ROE');
    Insert into BI_REGION (REGION_ID,REGION_NAME) values (7,'United Kingdom');

    Insert into BI_USER (USER_ID,FIRSTNAME,LASTNAME) values (1,'Adam,'Smith);
    Insert into BI_USER (USER_ID,FIRSTNAME,LASTNAME) values (2,'Steve','Jones');

    -- user with user id = 1 has access to division 1 , product 1 , sub product 1 in regons americas, asia, germany with ACCESS_LEVEL = write access (2) and also access to confidential data 
    Insert into BI_USER_ACCESS (USER_ACCESS_ID,USER_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,ACCESS_LEVEL, CONFIDENTIAL) values (1,1,1,1,1,1,2,'Y');
    Insert into BI_USER_ACCESS (USER_ACCESS_ID,USER_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,ACCESS_LEVEL, CONFIDENTIAL) values (1,1,1,1,1,2,2,'Y');
    Insert into BI_USER_ACCESS (USER_ACCESS_ID,USER_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,ACCESS_LEVEL, CONFIDENTIAL) values (1,1,1,1,1,3,2,'Y');

    -- user with user id = 1 has access to division 1 , product 2 , sub product 4 in regons americas, asia, germany with ACCESS_LEVEL = write access (2) and also NO access to confidential data 
    Insert into BI_USER_ACCESS (USER_ACCESS_ID,USER_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,ACCESS_LEVEL, CONFIDENTIAL) values (1,1,1,2,4,1,2,'N');
    Insert into BI_USER_ACCESS (USER_ACCESS_ID,USER_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,ACCESS_LEVEL, CONFIDENTIAL) values (1,1,1,2,4,2,2,'N');
    Insert into BI_USER_ACCESS (USER_ACCESS_ID,USER_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,ACCESS_LEVEL, CONFIDENTIAL) values (1,1,1,2,4,3,2,'N');

    -- employees in division 1 , product 1, sub product 1 and region americas and not confi.
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (1,'1','1','1',1,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (2,'1','1','1',1,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (3,'1','1','1',2,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (4,'1','1','1',2,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (5,'1','1','1',7,'N');

    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (11,'1','1','2',1,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (12,'1','1','2',2,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (13,'1','1','2',3,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (14,'1','1','2',2,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (15,'1','1','2',3,'N');

    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (111,'2','3','5',1,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (112,'2','3','5',2,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (113,'2','3','5',3,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (114,'2','3','5',4,'N');
    Insert into BI_EMPLOYEE (EMP_ID,DIVISION_ID,PRODUCT_ID,SUB_PRODUCT_ID,REGION_ID,CONFIDENTIAL) values (115,'2','3','5',5,'N');
Run Code Online (Sandbox Code Playgroud)

以下是我到目前为止所写的查询,但我不确定这是否是最佳方式.

    SELECT 
  *
FROM 
  BI_EMPLOYEE e 
JOIN BI_USER_ACCESS uad On uad.DIVISION_ID = e.DIVISION_ID and uad.USER_ID = 137
JOIN BI_USER_ACCESS uap On uap.PRODUCT_ID = e.PRODUCT_ID and uap.USER_ID = 137
JOIN BI_USER_ACCESS uasp On uasp.SUB_PRODUCT_ID = e.SUB_PRODUCT_ID and uasp.USER_ID = 137
JOIN BI_USER_ACCESS uar On uar.REGION_ID = e.REGION_ID  and uar.SUB_PRODUCT_ID = e.SUB_PRODUCT_ID and uar.USER_ID = 137
Run Code Online (Sandbox Code Playgroud)

编辑1:

我已经使用db脚本和一些示例数据更新了我的问题.

Sea*_*ean 0

该查询将USER_ACCESS表与表连接起来EMPLOYEE。它USER_ACCESS在提供的USER_ID(137) 上过滤表,然后联接将仅返回与表中存在的记录EMPLOYEE相同的员工。DIVISION_IDPRODUCT_IDUSER_ACCESS

select  e.*
from    BI_USER_ACCESS a
join    BI_EMPLOYEE e
on      a.DIVISION_ID = e.DIVISION_ID
and     a.PRODUCT_ID = e.PRODUCT_ID
where   a.USER_ID = 137
Run Code Online (Sandbox Code Playgroud)

它只选择EMPLOYEE数据(e.*),但如果需要,您可以(例如)将USER_ACCESS表连接到表并返回用户数据。USER但只要EMPLOYEE根据 中的 2 个字段返回数据USER_ACCESS,就应该可以了。

这能让你得到你想要的吗?