如何使一个表中的行优先于另一个表中的匹配行?

Cod*_*oet 5 postgresql

(key, value)将成对存储在两个不同的表中 -company_settingsbranch_settings. Akey可以不存在于表中,也可以存在于其中一个或两个表中。

如果key两个表中都存在,我想使用value存储在branch_settings表中的。否则,如果可用,我想回退到value存储在company_settings表中。

company_settings
-------------------------
| key    | value
-------------------------
| key.A  | 4             |
-------------------------
| key.B  | 5             |
-------------------------


branch_settings
-------------------------
| key    | value
-------------------------
| key.A  | 1             |
-------------------------
Run Code Online (Sandbox Code Playgroud)

因此,如果我查询key.A结果应该是1因为key.A两个表中都存在,并且我想为branch_settings表中的记录提供更高的优先级。

如果我查询key.B结果应该是5因为key.B只存在于company_settings表中。

ype*_*eᵀᴹ 4

如果您只需要 1 的值"key",您可以使用COALESCE()带有 2 个子查询的函数:

-- query 1a
SELECT COALESCE(
           (SELECT value FROM branch_settings WHERE key = prm.key),
           (SELECT value FROM company_settings WHERE key = prm.key)
       ) AS value 
FROM
    (VALUES ('key.A')) AS prm (key) ;
Run Code Online (Sandbox Code Playgroud)

您还可以展开 内的键列表VALUES,以搜索多个键:

-- query 1b
FROM
    (VALUES ('key.A'), ('key.B'), ..., ('key.Z')) AS prm (key) ;
Run Code Online (Sandbox Code Playgroud)

但是,如果您想要搜索多个键,将子查询转换为联接可能会更有效。任意两个LEFT连接:

-- query 2
SELECT prm.key, COALESCE(b.value, c.value) AS value 
FROM
    (VALUES ('key.A'), ('key.B'), ..., ('key.Z')) AS prm (key)
  LEFT JOIN branch_settings AS b ON b.key = prm.key
  LEFT JOIN company_settings AS c ON c.key = prm.key ;
Run Code Online (Sandbox Code Playgroud)

或一个FULL JOIN,类似于@James的答案:

-- query 3
SELECT key, COALESCE(b.value, c.value) AS value 
FROM
    (SELECT * FROM branch_settings 
     WHERE key IN ('key.A', 'key.B', ..., 'key.Z')
    ) AS b
  FULL JOIN 
    (SELECT * FROM company_settings 
     WHERE key IN ('key.A', 'key.B', ..., 'key.Z')
    ) AS b
  USING (key) ;
Run Code Online (Sandbox Code Playgroud)

查询 1b、2 和查询 3 之间存在细微差别。最后一个查询将在结果中仅提供至少一个表中出现的(参数)键。查询 1b 和 2 将在结果中包含所有(参数)键,其中NULL包含value可以在任一表中找到的键。