這種類型的問題是不使用非常簡單而有效的解決方案加入 (它甚至不使用兩個MINUS操作的結果的聯合) - 它只使用一個聯合和一個GROUP BY操作。該解決方案多年前在AskTom的一個主題中得到了開發,令人驚訝的是它並未被廣泛使用。例如(但不僅限於):https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:24371552251735
在你的情況,假設有上PERSON_ID
主鍵約束(這使得解決方案更簡單):
select max(flag) as flag, PERSON_ID, first_name, last_name, (etc. - all the columns)
from (select 'old' as flag, t1.*
from old_table t1
union all
select 'new' as flag, t2.*
from new_table t2
)
group by PERSON_ID, first_name, last_name, (etc.)
having count(*) = 1
order by PERSON_ID -- optional
;
如果一個PERSON_ID
所有的數據是在兩個表中相同,這將導致該組的計數爲2。所以它不會通過HAVING條件。唯一將有1個計數(因此每個只有一行!)的組或者是在一個表中而不在另一箇中的行。如果添加了一個人,那隻會顯示一行,並且標誌='新'。如果一個人被刪除了,你將只會得到一行,並帶有「舊」標誌。如果有更新,同樣PERSON_ID
會出現兩次,但由於至少有一個字段不同,所以兩行(一個標記爲'new',另一個爲'old')將位於不同的組中,它們將通過HAVING過濾器,他們將在輸出中。
這與您要求的略有不同;你將得到舊的和新的更新信息,標記爲「舊」和「新」。你說你只想要其中的一個,但沒有說明哪一個。這會讓你們兩人(無論如何都更有意義),但是如果你真的只想要一個,可以在上面的查詢中輕鬆完成。
注 - 外select
必須max(flag)
而不是flag
因爲flag
不是GROUP BY
列;但是它只是一行上的max()
,所以無論如何這將是該行的flag
。
添加 - OP表示他希望只爲具有更新(更改,修改)數據的人員獲取「新」行。在這種情況下,下面顯示的方法會將標誌更改爲「更改」。
with old_table (person_id, first_name, last_name) as (
select 101, 'John', 'Smith' from dual union all
select 102, 'Mary', 'Green' from dual union all
select 103, 'July', 'Dobbs' from dual union all
select 104, 'Will', 'Scott' from dual
),
new_table (person_id, first_name, last_name) as (
select 101, 'Joe' , 'Smith' from dual union all
select 102, 'Mary', 'Green' from dual union all
select 104, 'Will', 'Scott' from dual union all
select 105, 'Andy', 'Brown' from dual
)
-- end of test data; solution (SQL query) begins below this line
select case ct when 1 then flag else 'changed' end as flag,
person_id, first_name, last_name
from (
select max(flag) as flag, person_id, first_name, last_name,
count(*) over (partition by person_id) as ct,
row_number() over (partition by person_id order by max(flag)) as rn
from (select 'old' as flag, t1.*
from old_table t1
union all
select 'new' as flag, t2.*
from new_table t2
)
group by person_id, first_name, last_name
having count(*) = 1
)
where rn = 1
order by person_id -- ORDER BY clause is optional
;
輸出:
FLAG PERSON_ID FIRS_NAME LAST_NAME
------- ---------- --------- ---------
changed 101 Joe Smith
old 103 July Dobbs
new 105 Andy Brown
請顯示錶格模式,「真實」的示例輸入和輸出數據,而不是措辭。 – OldProgrammer
你應該用你正在使用的數據庫標記你的問題。 –
一旦你得到這個工作,我會建議使它成爲寫入歷史表的觸發器,並自動記錄這些更改。 – levelonehuman