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
我不太确定从哪里开始,因为我似乎无法接近。相交意味着我总是在标准中应用相同的字段,但事实并非如此。另外,不同的用户可以有不同数量的标准规则。非常感谢任何帮助!
谢谢!
如果可用于定义权限的详尽字段列表是固定的,那么您可以创建静态查询。如果字段列表不固定,只在运行时知道,那么你需要动态查询。
静态权限字段列表/静态查询
我们交叉加入 permissions
和 data
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 错误。
我正在研究如何向我有条件 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 |
我不太确定从哪里开始,因为我似乎无法接近。相交意味着我总是在标准中应用相同的字段,但事实并非如此。另外,不同的用户可以有不同数量的标准规则。非常感谢任何帮助!
谢谢!
如果可用于定义权限的详尽字段列表是固定的,那么您可以创建静态查询。如果字段列表不固定,只在运行时知道,那么你需要动态查询。
静态权限字段列表/静态查询
我们交叉加入 permissions
和 data
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 错误。