【问题标题】:Oracle SQL join queryOracle SQL 连接查询
【发布时间】:2012-06-26 10:36:27
【问题描述】:
TABLEA
LOGIN_ID ,COL1,COL2

TABLEB
LOGIN_ID, RESIGN_DATE, LAST_DATE, STATUS

我想从 TABLEA 中为特定 login_id 选择 login_id、resign_date 和 last_date

Login_ID 是 TABLEA 和 TABLEB 之间的链接。在 TABLEB 中,同一个 login_id 可以有多个记录。我想选择满足以下条件的resign_date和last_date。

1)if status is null for at least one of them
    it should identify that entry whose status is null
    System populate the resign_date and last_date of this entry 
2)if status is ‘Y’ for all of them
      resign_date = ’12/31/2050’ 
      last_date = ’12/31/2050’
3)If no entry in TABLEB
    resign_date = null
    last_date = null

如何为此编写一个 oracle sql 查询?

【问题讨论】:

  • :系统将如何填充空输入的日期...它将是什么日期?我问的是第一个条件
  • 如果 TABLEB 行的状态为空怎么办?
  • @GauravSoni 在这种情况下,我应该获得状态为空的条目的 resign_date 和 last_date ..
  • @TonyAndrews 只有一行状态为空.. 我忘了提..
  • @Ollie 我尝试使用左连接来编写它......我无法让它工作......

标签: sql oracle join


【解决方案1】:

如果您使用的是 Oracle 9i rel 2 或更高版本,这应该可以工作...

with c  as (select * from tableb where status is null)

select * 
from tablea
left join 
(
        select login_id, resign_date, last_date from c
        union
        select login_id, '12/31/2050', '12/31/2050' from tableb 
                where login_id not in (select login_id from c)
) d on tablea.login_Id = d.login_Id

我假设 tableB 中的状态是 Y 或 null

【讨论】:

    【解决方案2】:

    你可以使用analytic functions来做到这一点,这样做的好处是每张桌子只打一次。

    select distinct a.login_id,
        case when b.login_id is null then null
            when first_value(b.status) over (partition by b.login_id
                order by b.status nulls first) is null then b.resign_date
            when first_value(b.status) over (partition by b.login_id
                order by b.status nulls first) = 'Y' then date '2050-12-31'
        end as resign_date,
        case when b.login_id is null then null
            when first_value(b.status) over (partition by b.login_id
                order by b.status nulls first) is null then b.last_date
            when first_value(b.status) over (partition by b.login_id
                order by b.status nulls first) = 'Y' then date '2050-12-31'
        end as last_date
    from tablea a
    left join tableb b on b.login_id = a.login_id
    order by a.login_id;
    

    相关部分是case 语句 - 有两个但它们是相同的,除了从TABLEB 返回的列。案例分三个子句:

    when b.login_id is null then null
    

    如果TABLEB中没有匹配记录,因为外连接B.LOGIN_ID会为null;这符合您的第三个条件。

    when first_value(b.status) over (partition by b.login_id
        order by b.status nulls first) is null then b.resign_date
    

    first_value() 函数返回“最低”状态值,nulls first 表示如果任何匹配的TABLEB 记录具有空状态,则将首先看到该状态。所以这符合您的第一个条件,并为该空状态行使用 TABLEB.RESIGN_DATE

    when first_value(b.status) over (partition by b.login_id
        order by b.status nulls first) = 'Y' then date '2050-12-31'
    

    与上一个子句相同,但这次如果第一个值是Y,则不能有任何空值,因为又是nulls first。 (这是假设状态只能是null 或'Y',你的问题暗示 - 如果有任何其他状态,那么你的标准中没有指定行为)。因此,如果TABLEB 中的所有匹配行的状态为Y,这将使用与您的第二个条件匹配的固定日期值。

    请注意,我在这里使用了date literal;如果你愿意,你可以使用to_date('12/31/2050', 'MM/DD/YYYY'),但不要使用隐式转换,并假设特定的日期掩码会起作用。

    【讨论】:

      猜你喜欢
      • 2016-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-15
      • 2012-08-31
      • 1970-01-01
      • 2012-06-08
      • 2013-02-18
      相关资源
      最近更新 更多