我有一张桌子
userid | name | email | address
-------+------+------------------+-----------
1 | joe | joe@gmail.com | 123 Road
1 | joe | joe@gmail.com | null
1 | joe | null | null
我希望每次更改用户以及更改哪一行时都返回一行。所以
Userid | change
--------+-----------
1 | added address
1 | added email
如果一次改变了两件事,我想要改变'列包括两者。
目前我正在做这样的事情
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
比较每一栏。然后我将在另一个选择中连接电子邮件和地址以供显示。
想知道是否有更高效的东西,因为我将比较大量的列。可以在这里申请LAG吗?
由于系统限制,我无法使用SP或任何类型的循环。使用oracle。这里有什么想法?
提前致谢!
答案 0 :(得分:3)
这是我怎么做的。 (OP已经有了他的答案,但也许这将有助于未来的读者。)在每个属性的单独列中显示信息似乎要好得多 - 如果真的需要用于报告目的,它们可以连接在一起。我之前展示的格式更灵活 - 它允许查看用户有多少名称更改,以及电子邮件更改的数量。
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
;
<强>输出强>:
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.