[英]Compare 3 columns in same table for a group of rows
我必須根據 id 為每個組比較同一表的 3 列中的值。 最好說明我想要實現的目標:
create table test1 (id nvarchar(8), Name1 nvarchar(10), current_sem nvarchar(10), next_sem nvarchar(10), prev_sem nvarchar(10))
INSERT INTO test1 VALUES ('R001', 'Michael', 'Physics', 'Maths', 'Physics')
INSERT INTO test1 VALUES ('R001', 'Michael', 'Physics', 'Maths', 'Chemistry')
INSERT INTO test1 VALUES ('R003', 'Tim', 'Physics', 'Maths', 'Maths')
INSERT INTO test1 VALUES ('R002', 'John', 'Physics', 'Maths', 'Commerce')
INSERT INTO test1 VALUES ('R003', 'Tim', 'Maths', 'Maths', 'Physics')
INSERT INTO test1 VALUES ('R002', 'John', 'Maths', 'Commerce', 'Physics')
INSERT INTO test1 VALUES ('R002', 'John', 'Commerce', 'Physics', 'Maths')
INSERT INTO test1 VALUES ('R003', 'Tim', 'History', 'Civics', 'HomeEc')
INSERT INTO test1 VALUES ('R003', 'Tim', 'Drama', 'Chemistry', 'HomeEc')
表中的最后 3 列是: current_sem
、 next_sem
和prev_sem
。
對於每個 id,我想找到在 current_sem 或 prev_sum 中存在或不存在的 next_sem 的值,並顯示在名為“Sub_to_add”的偽列下。
對於相同的 id,還有另一個名為“Sub_to_remove”的偽列,其中包含在 next_sem 或 prev_sem 中不存在的 current_sem 的值。 因此,如果我們看到上述數據 id R001 (Michael) 將 Maths 作為 sub_to_add,因為 Maths 不存在於 R001 的 current_sem 或 prev_sem 中。
理想情況下不應顯示 R002,因為所有 next_sem 值都存在於 current_sem 或 prev_sem 中。 同樣沒有 sub_to_remove。
R003 將在 sub_to_add 下有 Civics;Chemistry,在 sub_to_remove 下有 History:Drama。
我不確定如何在代碼中顯示輸出,所以我添加了一個屏幕截圖。
我不能在WHERE
子句中使用( next_sem <> current_sem OR next_sem <> prev_sem)
,因為同一列的另一行中可能存在一個值 - R002 的示例。
id | Name1 | Sub_to_add | Sub_to_remove
--------------------------------------------------------------
R001 | Michael | Maths |
R003 | Tim | Civics:Chemistry | History;Drama
所以,我在這里尋求幫助。 此查詢將用於 SQL Server 2019 v15。
感謝您提醒我現在使用 PostgreSQL 而不是 SQL Server 是多么感激。 這非常痛苦,主要是因為您的數據模型,但也因為 SQL Server 的限制。
我對您的數據進行了標准化,這簡化了計算必要更改的過程。
with norm as (
select id, Name1, 'current' as sem, current_sem as subj from test1
union
select id, Name1, 'next' as sem, next_sem as subj from test1
union
select id, Name1, 'prev' as sem, prev_sem as subj from test1
), rules as (
select id, Name1, 'add' as change, subj
from norm t
where sem = 'next'
and not exists (
select 1
from norm
where id = t.id
and sem != t.sem
and subj = t.subj
)
union all
select id, Name1, 'remove' as change, subj
from norm t
where sem = 'current'
and not exists (
select 1
from norm
where id = t.id
and sem != t.sem
and subj = t.subj
)
)
select t.id, t.Name1,
string_agg(
case
when r.change = 'add' then subj
else null
end,
';'
) as sub_to_add,
string_agg(
case
when r.change = 'remove' then subj
else null
end,
';'
) as sub_to_remove
from (select distinct id, Name1 from test1) t
left join rules r
on r.id = t.id
group by t.id, t.Name1
order by t.id
;
db<> 在這里擺弄
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.