简体   繁体   English

Oracle SQL-基于逻辑使一对多连接一对一

[英]Oracle SQL - Making a one to many join one to one based on logic

Sorry for the broad title, I had a hard time coming up with a brief way of describing what I am looking to do. 抱歉,我的标题很宽泛,我很难想出一种简短的方式来描述我要做什么。 I have two tables (examples below) that I want to join but under a certain condition. 我有两个要联接的表(下面的示例),但是在一定条件下。

The main table has a field called "DateVal", the second table has a field called "Day". 主表有一个名为“ DateVal”的字段,第二个表有一个名为“ Day”的字段。 After joining on field "JoinField" I only want to keep rows where the day value in "DateVal" is less than the value of "Day". 加入字段“ JoinField”后,我只想保留行,其中“ DateVal”中的日值小于“日”的值。 However, if this criteria is met for multiple values of "Day" I only want it to keep the first instance. 但是,如果满足“ Day”的多个值的条件,我只希望它保留第一个实例。

In the second table below, for JoinField "A" there are three rows, for the first I only want it to return times when the day of the month is between 1-10, the second only with the day of the month is between 11-20, and the last 20-31. 在下面的第二个表中,对于JoinField“ A”有三行,对于第一行,我只希望它返回当月的日期在1-10之间的时间,第二行仅在当月的日期在11之间-20,最后20-31。

A left or inner join will bring back all values, the only way I can think of to get around this is to do a complete join and only return for min("Day"). 左联接或内部联接将带回所有值,我能想到的解决此问题的唯一方法是进行完整联接,只返回min(“ Day”)。 Can anyone think of a more efficient way? 谁能想到一种更有效的方法?

Thanks in advance. 提前致谢。

Table 1 表格1

-------------------------------
| ID | JoinField | DateVal    |
-------------------------------
| 1  | A         | 01/01/2014 |
| 2  | A         | 01/16/2014 |
| 3  | B         | 05/20/2013 |
-------------------------------

Table 2 表2

--------------------------------
| JoinField | Day | FieldToAdd |
--------------------------------
| A         | 10  | A          |
| A         | 20  | AA         |
| A         | 31  | AAA        |
| B         | 15  | B          |
| B         | 31  | BB         |
--------------------------------

Desired Results 所需结果

--------------------------------------------
| ID | JoinField | DateVal    | FieldToAdd |
--------------------------------------------
| 1  | A         | 01/01/2014 | A          |
| 2  | A         | 01/16/2014 | AA         |
| 3  | B         | 05/20/2014 | BB         |
--------------------------------------------

You can do this in a variety of ways. 您可以通过多种方式执行此操作。 I think a correlated subquery is the easiest way to express it, but unfortunately, the following doesn't work in Oracle: 我认为相关子查询是表达它的最简单方法,但是不幸的是,以下内容在Oracle中不起作用:

select t1.*,
       (select *
        from (select t2.*
              from table2 t2
              where t2.day < extract(day from t1.dateval)
              order by t2.day desc
             ) t
        where rownum = 1
       )
from table1 t1;

You can instead do this with join fancy window functions: 您可以改为使用join花式窗口函数执行此操作:

select *
from (select t1.*,
             row_number() over (partition by t1.id order by t2.day desc) as seqnum
      from table1 t1 left outer join
           table2 t2
           on t2.day < extract(day from t1.dateval)
     ) t
where seqnum = 1;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM