我正在一张看起来像这样的桌子上
user_id | key | scope | value
--------+-------------+-----------+-------
1 | someSetting | user | false
1 | someSetting | group | true
1 | someSetting | company | false
2 | someSetting | user | false
2 | someSetting | group | true
3 | someSetting | user | false
4 | someSetting | group | true
这些设置位于层次结构company -> group -> user
中,其中用户覆盖了该组,而该组又覆盖了公司。通过user_id
进行查询时,我想通过此层次结构有效地合并设置(如果存在)。对于以上示例,我想将其作为结果:
user_id | key | value
--------+-------------+-------
1 | someSetting | false
2 | someSetting | true
3 | someSetting | false
4 | someSetting | true
我目前正在从Postgres检索行之后进行合并操作,但是如果可以在查询本身中完成,则效率会更高。我查看了聚合函数,但看起来其中任何一个都不符合我的要求。
这个似乎很简单,我相信可以使用Postgres完成。任何指针表示赞赏!
答案 0 :(得分:1)
您可以将ROW_NUMBER()
窗口函数与PARTITION BY
和非常酷的ORDER BY
结合使用。
想法:
ROW_NUMBER
和user_id
自定义排序顺序为每条记录获取ORDER BY
。SELECT
您希望从CTE a
WHERE
行号获得的所有内容都是1。示例:
WITH a AS
(
SELECT user_id
, key
, scope
, ROW_NUMBER() OVER(PARTITION BY user_id
ORDER BY array_position(array['user','group','company'], scope)) AS rno
FROM test
)
SELECT user_id
, key
, scope
FROM a
WHERE rno = 1;
DBFiddle以显示其工作原理。
奖金: 如果您要创建函数来执行此操作,则甚至可以传入其他数组来设置自定义排序顺序。
答案 1 :(得分:0)
您要做的是将范围设置从单独的行更改为单独的列,因此您的记录集如下所示(请注意,我使用0表示false,1表示true):
+---------+-------------+--------------+---------------+-----------------+ | user_id | key | user_setting | group_setting | company_setting | +---------+-------------+--------------+---------------+-----------------+ | 1 | someSetting | 0 | 1 | 0 | | 2 | someSetting | 0 | 1 | NULL | | 3 | someSetting | 0 | NULL | NULL | | 4 | someSetting | NULL | 1 | NULL | +---------+-------------+--------------+---------------+-----------------+
为此,您有几种选择。这是其中之一,使用条件聚合。基本上,您将user_id
和key
分组,然后将聚合函数(可以是MIN
或MAX
)与CASE
语句组合在一起:>
WITH settings_pivot AS ( SELECT [user_id], [key], MIN(CASE WHEN [scope] = 'user' THEN [value] ELSE NULL END) AS user_setting, MIN(CASE WHEN [scope] = 'group' THEN [value] ELSE NULL END) AS group_setting, MIN(CASE WHEN [scope] = 'company' THEN [value] ELSE NULL END) AS company_setting FROM settings GROUP BY [user_id], [key] ) SELECT [user_id], [key], COALESCE(user_setting, group_setting, company_setting) AS derived_setting FROM settings_pivot
如果您只是通过settings_pivot CTE SELECT *
,您将获得我一开始拥有的数据透视表。但是,使用COALESCE
可以按照您指定的优先级。
注意:我正在使用SQL Server,因为我的计算机上的Postgres不想启动。因此,您必须用双引号代替方括号:"user_id"
,而不是[user_id]
。