0

我有一个相当复杂的 Oracle 查询,从多个表中获取数据。在其中一个连接中,我想要最好的记录,如果有的话。因此,左外连接。有一个开始日期字段,因此对于大多数记录,获取最大开始日期将使我获得最佳记录。但是,偶尔会有记录具有相同的开始日期。在这种情况下,还有一个状态字段。但是,最佳状态值不是最小值或最大值。“20”最好,“05”或“40”都可以,“70”最差。当返回多条记录时,如何设置查询以找到最佳选项?

所以,如果我有以下数据

Table1                       Table2
ID     otherData             ID      date      status    otherData
1      stuffa                1       jan-1-13  20        stuff93
2      stuff3                
3      stuff398              3       jan-2-13  20        stuff92
                             3       jan-2-13  70        stuff38
                             3       dec-3-12  20        stuff843

我将能够查询并获得以下信息:

1   stuffa    jan-1-13  20  stuff93
2   stuff3
3   stuff398  jan-2-13  20  stuff92

现在,我的查询如下,得到第二条记录 3,状态为 70:

select *
from table1 t1
left outer join
   (select *
    from table2 t2a
    where t2a.date = (select max(t2b.date)
                        from table2 t2b
                       where t2b.id = t2a.id)
    ) t2
  on (t2.id = t1.id)

有没有办法在 select 语句中设置有序枚举或类似的东西?就像是

rank() over ( partition by status order by ('20','05','40','70') rank
4

3 回答 3

1

如果有序枚举的元素很少,您可以使用它

 ........         order by 
                  CASE status WHEN '20' THEN 1
                              WHEN '05' THEN 2
                              WHEN '40' THEN 3
                              WHEN '70' THEN 4
                  END) rank
于 2013-02-15T17:38:41.970 回答
1

像这样将状态添加到订单中;

select *
  from (select t1.id,  t1.otherdata otherdatat1, t2.date, t2.status, t2.otherdata otherdatat2,
               rank() over (partition by t1.id order by t2.date desc,
                            case t2.status
                              when '20' then 1
                              when '05' then 2
                              when '40' then 3
                              when '70' then 4
                              else 5
                            end) rnk
          from table1 t1
               left outer join table2 t2
                            on t1.id = t2.id)
 where rnk = 1;
于 2013-02-15T17:43:57.057 回答
0

您可以执行以下操作:

select t1.id, t1.otherdata, t2.dt, t2.status, t2.otherdata 
from table1 t1
left outer join (
    select t2a.*,
        row_number() over (partition by id order by dt desc,
            case status
                when '20' then 1
                when '05' then 2
                when '40' then 3
                when '70' then 4
                else 5 end) as rn
    from table2 t2a
    ) t2 on t2.id = t1.id and t2.rn = 1
order by t1.id;

这假设即使有两个具有相同的状态,您也想要一个命中;你得到的两个中的哪一个是不确定的。如果你想要两者都可以使用rank()。无论哪种方式,您都根据日期(降序,因为您想要最大值)和您自己的状态值顺序为每条记录分配排名,然后只选择连接条件中排名最高的。

数据设置为:

create table table1(id number, otherdata varchar2(10));
create table table2(id number, dt date, status varchar2(2), otherdata varchar2(10));

insert into table1 values(1, 'stuffa');
insert into table1 values(2, 'stuff3');
insert into table1 values(3, 'stuff398');

insert into table2 values(1, date '2013-01-01', '20', 'stuff93');
insert into table2 values(3, date '2013-01-02', '20', 'stuff92');
insert into table2 values(3, date '2013-01-02', '70', 'stuff38');
insert into table2 values(3, date '2012-12-03', '20', 'stuff843');

...这给出了:

        ID OTHERDATA  DT        STATUS OTHERDATA
---------- ---------- --------- ------ ----------
         1 stuffa     01-JAN-13 20     stuff93    
         2 stuff3                                 
         3 stuff398   02-JAN-13 20     stuff92
于 2013-02-15T17:41:11.313 回答