【问题标题】:To find the new records in two days in SQL query在 SQL 查询中查找两天内的新记录
【发布时间】:2014-08-06 08:50:14
【问题描述】:

我正在使用查询从两个表中检查更改的叶子:-

with present_day 
as
(
select 1 as emp_id,'Sick Leave' as code , 9 as net_entitlement from dual
union
select 2 as emp_id,'Privilege Leave' as code , 5 as net_entitlement from dual
union
select 3 as emp_id,'Sick Leave' as code , 5 as net_entitlement from dual
union
select 5 as emp_id,'Sick Leave' as code , 10 as net_entitlement from dual
),
yester_day
as
(
select 1 as emp_id,'Sick Leave' as code , 10 as net_entitlement from dual
union
select 2 as emp_id,'Privilege Leave' as code , 5 as net_entitlement from dual
union
SELECT 3 AS EMP_ID,'Sick Leave' AS CODE , 6 AS NET_ENTITLEMENT FROM DUAL
UNION
SELECT 4 AS EMP_ID,'Sick Leave' AS CODE , 6 AS NET_ENTITLEMENT FROM DUAL
)

select a.emp_id,a.code,
a.net_entitlement
from present_day a,
YESTER_DAY B
WHERE A.EMP_ID=B.EMP_ID
AND A.CODE=B.CODE
and a.net_entitlement<>b.net_entitlement

在这个查询中,那些细节即将发生变化,但我需要那些昨天存在而不是现在的行,反之亦然......如何去做?

上面的查询给出了输出:-

emp_id  code          net_entitlement
1     Sick Leave            9
3     Sick Leave            5

需要的输出是:

emp_id  code          net_entitlement
1   Sick Leave  9
3   Sick Leave  5
4   Sick Leave  6
5   Sick Leave  10

我尝试使用 Union,但如果我使用,性能会受到影响:-

UNION 
select a.emp_id,a.code,
a.net_entitlement
from present_day a,
YESTER_DAY B
WHERE A.EMP_ID NOT IN B.EMP_ID
or B.EMP_ID NOT IN A.EMP_ID;

【问题讨论】:

    标签: sql oracle union


    【解决方案1】:

    与 Lennart 的想法相同(或至少是他的答案的第一个版本),但您还需要合并选择列表中的值:

    ...
    select coalesce(a.emp_id, b.emp_id) as emp_id,
      coalesce(a.code, b.code) as code,
      coalesce(a.net_entitlement, b.net_entitlement) as net_entitlement
    from present_day a
    full outer join yester_day b
    on a.emp_id = b.emp_id
    and a.code = b.code
    where a.net_entitlement is null
    or b.net_entitlement is null
    or a.net_entitlement <> b.net_entitlement;
    
        EMP_ID CODE            NET_ENTITLEMENT
    ---------- --------------- ---------------
             1 Sick Leave                    9 
             3 Sick Leave                    5 
             4 Sick Leave                    6 
             5 Sick Leave                   10 
    

    SQL Fiddle.

    完全外连接包括在一个或两个表中的记录; where 子句排除了两者中具有相同 net_entitlement 值的那些。 (我更喜欢显式检查 null 而不是依赖幻数,即使 -1 在这里看起来很安全)。

    【讨论】:

    • 记录超过 100 条的表花费了太多时间
    • 100 行应该仍然是微不足道的;成千上万的人也应该如此。您的真实表中有多少行,它们是否都在emp_id, code 上编制索引?您可能需要查看执行计划以了解它在做什么,如果它没有使用您期望的索引。
    • 我从一个有 10 天历史的存档表中获取......并且需要 11 分钟才能完全执行@Alex Poole
    • @user3809240 - 你需要查看执行计划,看看它是否在做一些意想不到的事情。
    • 对不起,没明白执行计划的意思?以什么方式?
    【解决方案2】:

    您可以尝试类似(未经测试):

    select a.* from
    from present_day a
    left join YESTER_DAY B
       on A.EMP_ID=B.EMP_ID
      AND A.CODE=B.CODE
    where a.net_entitlement<>coalesce(b.net_entitlement,-1)
    union all
    select b.*
    from present_day a
    right join YESTER_DAY B
       on A.EMP_ID=B.EMP_ID
      AND A.CODE=B.CODE
    where coalesce(a.net_entitlement,-1)<>b.net_entitlement
    

    【讨论】:

    • @Alex 解决方案要好得多,坚持使用那个。无论如何我都会留下这个。
    猜你喜欢
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 2020-11-12
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    相关资源
    最近更新 更多