Postgresql

為每一行顯示用於選擇它的條件的標誌(指示器)

  • February 27, 2021

假設我有桌子foo。我想使用不同的條件(cond_1, cond_2, …, cond_n-順序很重要)過濾這個表的行,組合在一個析取中,即:

SELECT * FROM foo WHERE cond_1 OR cond_2 OR ... OR cond_n;
  1. 是否可以(在 PostgreSQL 13 中)區分每一行使用哪個條件cond_i來選擇它?因為我說順序很重要,所以問題可以重新表述為 - 我想知道cond_i為每一行選擇行的第一個。

現在考慮我foo為此目的在一個專欄中,例如selected_by

  1. 是否可以區分每一行使用哪個條件cond_i來選擇它並將其儲存在其中selected_by?(與第一個問題相同,但針對 UPDATE 語句)

有兩件事很重要:條件的順序(如前所述);性能(即表foo可能有很多行,條件數很少,最多5-10)。

如果您的條件是互斥的(您只關心匹配您控制的訂單的第一個),那麼您可以只使用一列:

SELECT *,
 CASE 
   WHEN name = 'meatfeast' THEN 'name' 
   WHEN diet = 'vegan' THEN 'diet' 
 END as reason_for_appearing
FROM
 pizza
WHERE
 name = 'meatfeast' OR diet = 'vegan'

您重複您的 where 條件作為案例的單個子句 when,(按照您關心它們的順序)


如果它們不是互斥的,並且您想知道它可能匹配的所有原因,您將需要多個列..

SELECT *,
 CASE WHEN name = 'john' THEN 'yes' END as because_of_name,
 CASE WHEN city = 'Chicago' THEN 'yes' END as because_of_city
FROM
 person
WHERE 
 name = 'john' OR city = 'chicago'

..除非你想真正參與一個巨大的案例,當所有條件組合(這是2 ^ N,我相信你可以想像)

或者您也可以選擇做某種連接,您可以通過程式方式將其分開,或者使用者可以閱讀

SELECT *,
 CONCAT(
   CASE WHEN name = 'john' THEN 'name' END,
   CASE WHEN city = 'Chicago' THEN ' city' END 
 ) as because_of
FROM
 person
WHERE 
 name = 'john' OR city = 'chicago'

我想這取決於你想用它做什麼

您可以計算條件遮罩(例如二進製表示):

CREATE TABLE test (id INT, val INT);
INSERT INTO test VALUES (1,1), (1,2), (2,1), (2,2);
SELECT *, 
       (id=1 AND val=1)::INT + 2 * (id<val)::INT + 4 * ((id+val)!=3)::INT conditions_mask_bin,
       (id=1 AND val=1)::INT + 10 * (id<val)::INT + 100 * ((id+val)!=3)::INT conditions_mask_dec
FROM test
WHERE (id=1 AND val=1)
   OR (id<val)
   OR ((id+val)!=3);
編號 | 值 | conditions_mask_bin | conditions_mask_dec
-: | --: | ------------------: | ------------------:
 1 | 1 | 5 | 101
 1 | 2 | 2 | 10
 2 | 2 | 4 | 100

db<>在這裡擺弄

引用自:https://dba.stackexchange.com/questions/286062