I have a table
userid | name | email | address
-------+------+------------------+-----------
1 | joe | joe@gmail.com | 123 Road
1 | joe | joe@gmail.com | null
1 | joe | null | null
I want to return a row for each time the user has been changed and which row was changed. So
Userid | change
--------+-----------
1 | added address
1 | added email
If two things were changed at once, I want the 'Change' column to include both.
Currently I am doing something like this
SELECT
CASE WHEN table1.email <> table2.email THEN 'Email Change'
WHEN table1.email IS NULL AND table2.email IS NOT NULL THEN 'Email addition'
END email,
CASE WHEN table1.address <> table2.address THEN 'Address Change'
WHEN table1.address IS NULL AND table2.address IS NOT NULL THEN 'Address addition'
END address
FROM usertable table1 JOIN usertable table2 ON table1.userid = table2.userid
And comparing each column. Then I will concatenate email and address in another select for display.
Was wondering if there is anything more efficient since I will be comparing a good amount of columns. Could LAG be applied here?
I cannot use SP or any type of loop due to restrictions of system. using oracle. Any ideas here?
Thanks in advance!
Here's how I would do this. (The OP has his answer already, but perhaps this will help future readers.) It seems a lot better to have the information in separate columns for each attribute - then they can be concatenated if really needed for reporting purposes. The format I show before is more flexible - it allows to see how many name changes a user had, vs. how many email changes.
with
base_table ( userid, eff_dt, name, email, address ) as (
select 1, date '2015-10-22', 'joe', 'joe@gmail.com', '123 Road' from dual union all
select 1, date '2016-03-20', 'joe', 'joe@gmail.com', null from dual union all
select 1, date '2016-09-01', 'joe', null , null from dual
)
select userid, eff_dt, name, email, address,
case when lag(name) over (partition by userid order by eff_dt) is null
and name is not null then 'added'
when lag(name) over (partition by userid order by eff_dt) is not null
and name is null then 'deleted'
when lag(name) over (partition by userid order by eff_dt) != name
then 'updated' end as name_changes,
case when lag(email) over (partition by userid order by eff_dt) is null
and email is not null then 'added'
when lag(email) over (partition by userid order by eff_dt) is not null
and email is null then 'deleted'
when lag(email) over (partition by userid order by eff_dt) != email
then 'updated' end as email_changes,
case when lag(address) over (partition by userid order by eff_dt) is null
and address is not null then 'added'
when lag(address) over (partition by userid order by eff_dt) is not null
and address is null then 'deleted'
when lag(address) over (partition by userid order by eff_dt) != address
then 'update end as address_changes
from base_table
;
Output :
USERID EFF_DT NAME EMAIL ADDRESS NAME_CHANGES EMAIL_CHANGES ADDRESS_CHANGES
------ ---------- ---- ------------- -------- ------------ ------------- ---------------
1 2015-10-22 joe joe@gmail.com 123 Road added added added
1 2016-03-20 joe joe@gmail.com deleted
1 2016-09-01 joe deleted
3 rows selected.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.