SQL: Utilizing criteria table 不同类型的标准应用于不同的领域

SQL: Utilizing criteria table with different types of criteria applied to different fields

我正在研究如何向我有条件 table 的用户提供权限,该条件有 field/value 对匹配我数据集中的不同字段。

以下是权限table。

Field Value Permissioned user
region AMER Kim
manager Chris Kim
division Sales Kim
region EMEA Julie
manager Jim Julie

这是数据的格式。不同的字段代表上面的不同字段。可能有 8 个或更多不同的字段(例如地区、业务部门、部门负责人等),因此我需要一种扩展到我的虚拟数据集之外的方法。

EMP ID region division manager
1 AMER Marketing Chris
2 AMER Sales Chris
3 EMEA Sales Chris
4 AMER Sales Jim
5 EMEA Marketing Jim
6 EMEA Sales Jim

所需的输出将标准应用于不同的字段。

Permisioned User EMP ID region division manager
Kim 2 AMER Sales Chris
Julie 5 EMEA Marketing Jim
Julie 6 EMEA Sales Jim

我不太确定从哪里开始,因为我似乎无法接近。相交意味着我总是在标准中应用相同的字段,但事实并非如此。另外,不同的用户可以有不同数量的标准规则。非常感谢任何帮助!

谢谢!

如果可用于定义权限的详尽字段列表是固定的,那么您可以创建静态查询。如果字段列表不固定,只在运行时知道,那么你需要动态查询。

静态权限字段列表/静态查询

我们交叉加入 permissionsdata table。 然后,我们将行按"Permissioned user""EMP ID"进行分组,由于[=]中的聚合函数bool_and,我们只保留满足(字段,值)对应关系的分组行18=] 子句。 最后我们添加数据的所有列 table 并按 "EMP ID" :

排序
WITH list AS
(
SELECT p."Permissioned user"
     , d."EMP ID"
  FROM data AS d
 CROSS JOIN permissions AS p
 GROUP BY p."Permissioned user", d."EMP ID"
HAVING bool_and( CASE 
                   WHEN p.field = 'region' THEN p.value = d.region
                   WHEN p.field = 'manager' THEN p.value = d.manager
                   WHEN p.field = 'division' THEN p.value = d.division
                   WHEN [...]  -- insert here the rest of the fields list
                   ELSE FALSE
                 END
               )
)
SELECT l."Permissioned user", d.*
  FROM list AS l
 INNER JOIN data AS d
    ON d."EMP ID" = l."EMP ID"
 ORDER BY d."EMP ID" ;

可变权限字段列表/动态查询

动态查询允许根据仅在 运行 时间已知的条件搜索数据。它必须嵌入到 plpgsql 函数中,该函数将 return 动态查询的结果。对于tablepermissions中的每个“Permissioned user”,原理是生成与WHERE子句匹配的where_clause字符串在 table data 中搜索的查询。 “许可用户”where_clause 被传递给 plpgsql 函数 permissioned_user,其中包含动态查询和 returns “EMP ID”列表 in table data :

CREATE OR REPLACE FUNCTION permissioned_user 
( INOUT "Permissioned user" text
, IN where_clause text
, OUT "EMP ID" integer
)
RETURNS setof record LANGUAGE plpgsql IMMUTABLE AS
$$
BEGIN  
RETURN QUERY EXECUTE E'
    SELECT ' || quote_nullable("Permissioned user") || E'
         , "EMP ID"
      FROM data AS d
     WHERE ' || where_clause ;
END ;
$$

然后下面的查询return是预期的结果。首先,它生成与 table permissions 中每个“许可用户”关联的 where_clause 字符串。然后它调用 function permissioned_user(),获取 "EMP ID" 列表并与 data 列的其余部分合并:

WITH list AS
(   SELECT "Permissioned user"
         , string_agg('d.' || quote_ident(Field) || E' = \'' || quote_nullable(Value) || E'\'', ' AND ') AS where_clause
      FROM permissions
     GROUP BY "Permissioned user"
)
SELECT a."Permissioned user", d.*
  FROM list AS l
 CROSS JOIN LATERAL permissioned_user(l."Permissioned user", l.where_clause) AS a
 INNER JOIN data AS d
    ON d."EMP ID" = a."EMP ID"
  ORDER BY a."EMP ID"

请注意,table permissions 中的任何 Field 值与 data [=66] 中的列名称不对应=] 将生成 SQL 错误。