SQL:利用标准表,将不同类型的标准应用于不同的字段
Posted
技术标签:
【中文标题】SQL:利用标准表,将不同类型的标准应用于不同的字段【英文标题】:SQL: Utilizing criteria table with different types of criteria applied to different fields 【发布时间】:2021-12-30 15:32:58 【问题描述】:我正在研究如何向具有标准表的用户提供权限,该标准表具有与我的数据集中不同字段匹配的字段/值对。
下面是权限表。
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 |
我不确定从哪里开始,因为我似乎无法靠近。相交意味着我总是在标准中应用相同的字段,但事实并非如此。另外,不同的用户可以有不同数量的标准规则。非常感谢任何帮助!
谢谢!
【问题讨论】:
【参考方案1】:如果可用于定义权限的详尽字段列表已修复,则您可以创建静态查询。如果字段列表不是固定的并且仅在运行时才知道,那么您需要动态查询。
权限字段静态列表/静态查询
我们交叉加入permissions
和data
表。
然后,我们按"Permissioned user"
和"EMP ID"
对行进行分组,并且由于HAVING
子句中的聚合函数bool_and
,我们只保留所有满足(字段,值)对应的分组行。
最后我们添加数据表的所有列,并按“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 函数中。对于表permissions
中的每个“Permissioned user”,其原理是生成与表data
中查询搜索的WHERE
子句匹配的where_clause 字符串。 "Permissioned user" 和 where_clause 被传递给 plpgsql 函数permissioned_user
,其中包含动态查询并返回 "EMP ID" 列表 em> 在表中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 ;
$$
然后下面的查询返回预期的结果。首先,它生成与表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"
请注意,表permissions
中的任何字段 值与data
表中的列名不对应都会产生SQL 错误。
【讨论】:
很好的解释!作为一个中等级别的 SQL 用户,我现在被卡住的感觉并不那么糟糕 :)以上是关于SQL:利用标准表,将不同类型的标准应用于不同的字段的主要内容,如果未能解决你的问题,请参考以下文章