簡體   English   中英

Postgres選擇並合並行

[英]Postgres select and merge rows

我正在一張看起來像這樣的桌子上工作:

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來完成。 任何指針表示贊賞!

您可以將ROW_NUMBER()窗口函數與PARTITION BY和非常酷的ORDER BY

理念:

  1. 為具有相同user_idORDER BY自定義排序順序的每條記錄獲取ROW_NUMBER
  2. 從CTE a WHERE行號為1中SELECT您想要的所有內容。

例:

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演示它的工作原理。


獎勵:如果您要創建一個函數來執行此操作,您甚至可以傳入其他數組來設置自定義排序順序。

您要做的是將范圍設置從單獨的行更改為單獨的列,因此您的記錄集如下所示(請注意,我使用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_idkey分組的,然后將聚合函數(可以是MINMAX )與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可以按照您指定的優先級進行操作。

注意 :由於我的計算機上的Postgres不想啟動,因此我正在使用SQL Server。 因此,您必須將方括號替換為雙引號: "user_id"而不是[user_id]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM