【问题标题】:Select from one table if present,else select from another having latest date如果存在则从一个表中选择,否则从另一个具有最新日期的表中选择
【发布时间】:2021-10-13 10:04:05
【问题描述】:

共有三个表 T1 和 T2 和 T3

T3 存储人员详细信息 T1 存储人的主要电话号码, T2 存储人员的非主要电话号码。

T1

Personid Primaryphone dateload
1 1001 02/08/21
2 1002 03/07/21
4 1004 04/08/20
5 1005 08/09/20

T2

Personid NonPrimphone dateload
1 1011 12/03/21
3 1003 20/02/21
4 1024 30/12/21
6 1006 08/08/20
3 1007 04/04/21
3 1008 21/08/21

T3

Per_numb person_id
501 1
502 2
503 3
504 4
505 5
506 6

我想要的是,从 T3 和他们的电话号码中选择所有人员编号,标准是,如果此人有主电话号码,则选择该号码,如果没有主电话号码,则从具有最新日期加载的非主表中选择电话号码。

O/p

Per_numb phonenumber
501 1001
502 1002
503 1008
504 1004
505 1005
506 1006

我也想加入这三个表,不要使用子查询,因为子查询会使执行变慢。

【问题讨论】:

  • 到目前为止您尝试过什么?您是否查看了 LEFT JOINS 和 CASE 语句以从哪个表中选择哪个字段?
  • 我尝试将 tableT3 与 T1 和 T2 连接起来,并使用案例,但问题在于连接 T1 和 T2 时,如果一个人同时拥有主要电话和非主要电话,我会同时获得两个电话号码。我想要什么时候选择来自T1的电话号码时,在我的情况下,所有这些表都不应该在我的情况下有lakh的行,所以我的表现非常受损。 span>
  • “因为子查询使执行变慢”?你从哪里得到这个想法的?您对 Oracle 优化器的工作原理了解多少?如果您的查询中有子查询并且优化器认为连接会更好,优化器将应用该优化本身,它不需要您的帮助(当然不需要像您这样的简单查询)!

标签: sql oracle


【解决方案1】:

一种方法使用coalesce()

select t3.*,
       coalesce( (select t1.primaryphone
                  from t1
                  where t1.personid = t3.personid
                 ),
                 (select t2.phone
                  from t2
                  where t2.personid = t3.personid
                  order by t2.dateload desc
                  fetch first 1 row only
                 )
               ) a_good_phone
from t3;

【讨论】:

    【解决方案2】:
    select distinct Per_numb , coalesce(Primaryphone,NonPrimphone)
    from table3 t3
    left join table1 t1 
      on t1.Personid = t3.Personid
    outer apply (
    select * from table2 t2
    where t2.personid = t3,personid
    order by dateload desc 
    limit 1
    ) t2
    

    【讨论】:

      【解决方案3】:

      我相信下面的查询是最优的,或者接近最优的。不要猜测什么会使查询“快”或“慢”,而是根据您的实际数据进行测试。

      关于一致性的注意事项:“相同”列在两个表中称为 personid,但在第三个表中称为 person_id(带有下划线)。这种不一致会让您的开发人员发疯。你能解决这个问题吗?

      select t3.per_numb, sq.phone
      from   t3 left outer join
             (
               select  personid, primaryphone as phone
                 from  t1
               union all
               select  personid, nonprimphone
                 from  t2
                 where (personid, dateload) in
                       ( select personid, max(dateload)
                         from   t2
                         where  personid not in (select personid from t1)
                         group  by personid
                       )
             ) sq on t3.person_id = sq.personid
      order  by per_numb    --  if needed
      ;
      

      【讨论】:

        【解决方案4】:

        使用FIRST_VALUE()窗口函数获取最新的NonPrimphoneCOALESCE()T1T2中选择号码:

        SELECT DISTINCT t3.Per_numb,
               COALESCE(
                 t1.Primaryphone,
                 FIRST_VALUE(t2.NonPrimphone) OVER (PARTITION BY t3.person_id ORDER BY t2.dateload DESC) 
               ) phonenumber
        FROM Table3 t3 
        LEFT JOIN Table1 t1 ON t1.Personid = t3.person_id
        LEFT JOIN Table2 t2 ON t2.Personid = t3.person_id
        ORDER BY t3.Per_numb;
        

        请参阅demo

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-08-20
          • 2021-12-14
          • 2019-03-05
          • 2014-02-21
          • 1970-01-01
          • 1970-01-01
          • 2016-07-02
          相关资源
          最近更新 更多