簡體   English   中英

SQL 查詢將多列中的值映射到另一個表中的不同值

[英]SQL query map values in multiple columns to different value in another table

我有一個包含 1000 多列的主表,其中許多列包含唯一代碼。 這些代碼映射到另一個表中的值。 我正在嘗試使用映射值生成主表的副本。

主表

id   name    cty    city   segment
==   ====    ===    ===    ===
01   John    001    012    081
02   Sam     001    019    110
03   Lee     005    029    110

映射表

id   code    value
==   ====    ===
01   001     USA
02   012     San Francisco
03   019     New York City
04   005     Canada
05   029     Vancouver
06   081     Retail
07   110     Corporate

我想要的輸出:

id   name    cty     city            segment
==   ====    ===     ===             ===
01   John    USA     San Francisco   Retail
02   Sam     USA     New York City   Corporate
03   Lee     Canada  Vancouver       Corporate

當然,我可以運行許多連接,如下所示:

SELECT m.id, m.name, z1.value, z2.value, z3.value
FROM Master m
INNER JOIN mapping z1 ON m.cty = z1.code
INNER JOIN mapping z2 ON m.city = z2.code
INNER JOIN mapping z3 ON m.segment = z3.code

但是,有 100 列映射到代碼。 是否有一個 SQL 查詢可以達到相同的結果或者比編寫多個INNER JOINS執行起來更便宜?

理想的結果是我可以運行一個簡單的SELECT * FROM Master...在這里我不必拼出每一列,同時將所有代碼映射到它們各自的值,同時我看不到代碼。

我相信如果您的結果集依賴於它,您將無法逃避這數百個連接,但是您可以通過將它們保存到VIEW來將它們隱藏起來:

創建視圖

CREATE VIEW my_view AS
SELECT m.id, m.name, z1.value as city1, z2.value as city2, z3.value as segment
FROM Master m
INNER JOIN mapping z1 ON m.cty = z1.code
INNER JOIN mapping z2 ON m.city = z2.code
INNER JOIN mapping z3 ON m.segment = z3.code;

查詢視圖

SELECT * FROM my_view;

視圖只是執行先前保存的查詢並顯示其結果。 但如果您的查詢太耗時,您可以創建一個所謂的MATERIALIZED VIEW 顧名思義,它是物理創建在磁盤上的,不需要每次都執行其原始查詢。

create MATERIALIZED VIEW只需將MATERIALIZED添加到語句中

CREATE MATERIALIZED VIEW my_view AS
SELECT ...

refresh其值只是做

REFRESH MATERIALIZED VIEW my_view;

顯然所有值都是字符串(文本、varchar),您可以構建映射的 JSON 鍵/值對,然后動態訪問鍵。

我認為這不會更快(甚至可能更慢),但它只需要一個連接並且名稱是動態的。

select m.id, m.name, 
       mp.mappings ->> 'cty' as cty,
       mp.mappings ->> 'city' as city,
       mp.mappings ->> 'segment' as segment,
       mp.mappings as all_mappings
from master m
  left join lateral (
    select jsonb_object_agg(k, value) as mappings
    from mapping ma
      join jsonb_each_text(to_jsonb(m) - 'id' - 'name') as t(k,val)
        on ma.code = t.val
  ) mp on true

在線示例

jsonb_each_text(to_jsonb(m) - 'id' - 'name')創建一個 JSON 值,其中主表中的列名是鍵。 鍵(=列名稱) idname將從該 JSON 中刪除。

然后使用那里的值連接映射表。 結果是聚合成單個 JSON 值,其中主表中的列名是鍵,映射表中的值是值。

沒有真正的方法可以單獨指定每個輸出列。 如果您不是真的不需要各個列,您可以選擇mp.mappings並將所有值作為單個 JSON 獲取。

暫無
暫無

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

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