想象一下這張桌子:
id col1 col2 col3 col4
1 A A C
2 B B B
3 D D
我想添加一列,告訴我該行的所有非空值是否匹配。
所以理想的輸出是:
id col1 col2 col3 col4 is_a_match
1 A A C FALSE
2 B B B TRUE
3 D D TRUE
我努力了:
select *,
case
when col1 = col2
and col2 = col3
and col3 = col4
then 'TRUE'
else 'FALSE'
end as is_a_match
from my_table
但false由于空值,會全部回傳。
實作上述輸出的最佳方法是什么?
uj5u.com熱心網友回復:
您可以將列轉換為行,計算不同的值。這將自動忽略 NULL 值:
select t.*,
(select count(distinct x.col)
from (
values (t.col1),
(t.col2),
(t.col3),
(t.col4)
) as x(col)
where x.col is not null) = 1 as is_a_match
from the_table t
如果您不想手動列出所有列,則可以使用一些 JSON 魔術將列轉換為行以計算不同的值:
select t.*,
(select count(distinct x.val)
from jsonb_each_text(to_jsonb(t) - 'id') as x(col, val)
where x.val is not null) = 1
from the_table t
uj5u.com熱心網友回復:
如果列數是可變的,則翻入和翻出 jsonb 可以為您節省一些剪切和粘貼:
with pivots as (
select d.id, c.k, c.v
from de_data d
cross join lateral jsonb_each_text(to_jsonb(d)) as c(k,v)
where c.k != 'id'
and c.v is not null
), match_check as (
select id, count(distinct v) = 1 as is_a_match
from pivots
group by id
)
select d.*, mc.is_a_match
from de_data d
left join match_check mc on mc.id = d.id;
db<>在這里擺弄
uj5u.com熱心網友回復:
簡單的布爾邏輯 - 看起來有點尷尬,但我敢打賭這是最快的方法:
SELECT *
, COALESCE(NOT (col1 <> col2 OR col1 <> col3 OR col1 <> col4
OR col2 <> col3 OR col2 <> col4
OR col3 <> col4), true) AS is_a_match
FROM tbl;
任何非空、不相等的對都構成核心運算式true。反相NOT,默認為真COALESCE。
或者更接近您最初的嘗試,這并不遙遠:
SELECT *
, CASE WHEN (col1 <> col2 OR col1 <> col3 OR col1 <> col4
OR col2 <> col3 OR col2 <> col4
OR col3 <> col4)
THEN false
ELSE true END is_a_match
FROM tbl;
db<>在這里擺弄
無論哪種方式,關鍵是顛倒邏輯:要忽略與 NULL 值的比較,查找不匹配(僅true針對兩個非空值),而不是匹配。
代碼因更多列而膨脹。但是對于滿是柱子的手來說,遍歷所有對子是最快的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/491566.html
標籤:sql PostgreSQL 无效的 案子 布尔逻辑
上一篇:SQL:日期范圍來自多行
下一篇:在一張表中捕獲兩張表之間的差異
