Sql 带联接的内部查询中的ORDERBY子句

Sql 带联接的内部查询中的ORDERBY子句,sql,plsql,oracle11g,Sql,Plsql,Oracle11g,Products表有两个条目-伪(标志='Y')和实际(标志='N') 如果没有伪产品,则需要获取实际产品 上述查询导致编译错误。 内部查询可能返回多条记录,但我只需要第一条记录(即“Y”记录。如果找不到“Y”记录,则需要“N”记录)。有点过火,但应该可以: create table items(item_pk integer, pgid integer, prod_id integer, PRIMARY KEY(item_pk)); create table products(prod_id

Products表有两个条目-伪(标志='Y')和实际(标志='N')

如果没有伪产品,则需要获取实际产品

上述查询导致编译错误。
内部查询可能返回多条记录,但我只需要第一条记录(即“Y”记录。如果找不到“Y”记录,则需要“N”记录)。

有点过火,但应该可以:

create table items(item_pk integer, pgid integer, prod_id integer, PRIMARY KEY(item_pk));
create table products(prod_id integer, version  integer, pgid  integer, flag char(1), PRIMARY KEY(prod_id));

insert into items(item_pk,  pgid) values (1,  21);
insert into items(item_pk, pgid) values(2,  31);
insert into products(prod_id, version, pgid, flag) values (11, 101,  21, 'Y');
insert into products(prod_id, version, pgid, flag) values (22, 101,  21, 'N');
insert into products(prod_id, version, pgid, flag) values(33, 101, 31, 'N');

   declare 
    prod_version NUMBER := :1 ;  
    begin  
    update items i set i.prod_id = ( 
     select p.prod_id from products p where 
     p.version = prod_version and p.pgid = i.pgid and rownum =1 
     order by p.flag desc
    ) where i.xyz is null
    commit; end;    

您需要在更新查询中进行另一次选择。我想应该是这样的

select prod_id
from (
    select p.prod_id, ROW_NUMBER() OVER (ORDER BY p.flag DESC) as rn
    from products p
    where p.version = prod_version and p.pgid = i.pgid
    )
where rn=1

我没有可用的ide来检查我的语法。我在一个文本编辑器中做这件事,所以可能会有bug

我总是尽量避免在查询中使用任何类型的rownum,因此这可能需要使用“N”值的子查询

update items i set i.prod_id = ( 
  select prod.id from (
    select p.prod_id,rownum rn from products p where 
    p.version = prod_version and p.pgid = i.pgid
  order by p.flag desc) x 
    where x.rn=1
) where i.xyz is null
但是,您可以始终使用plsql并执行类似的操作

declare 
   prod_version NUMBER := :1 ;  
begin  
  update items i set i.prod_id = (select p.prod_id
                                    from products p
                                   where p.version = prod_version
                                     and p.pgid = i.pgid
                                     and (p.flag = 'Y' 
                                          or (p.flag = 'N' and 0 = (select count(*)
                                                                  from products p2
                                                                 where p2.version = prod_version
                                                                   and p2.pgid = i.pgid
                                                                   and p2.flag = 'Y')
                                              )
                                          )
                                 )
  where i.xyz is null
  commit;
end;

正如我上面所说的,我可以随意处理这个问题,所以请仔细检查语法。

@YasinOkumus:内部查询可能会返回两条记录。如果存在,我需要“Y”记录,否则需要“N”记录。我晚了些时候才知道这一点,所以我删除了我的评论。对不起。我正在写一个答案,我希望这次我答对了,你能得到答案。:)“and rownum=1”是否试图只获取一条记录?我尝试了此操作,但无法识别内部查询中的“I”。我现在无法尝试,但这很奇怪。也许你应该考虑修改更新查询,因为这里是用这两个表(项目和产品)的连接来写的:在阅读之后,你可能想把关键字“区分”添加到那个查询中。但我不知道他桌上有什么。
declare
  temp_prod_id number;
  prod_version NUMBER := :1 ; 

begin
  for v_rec in (select id, pgid from items where xyz is null) loop
    begin
      select prod_id into temp_prod_id from products p
       where p.version = prod_version
         and p.pgid = v_rec.pgid
         and p.flag = 'Y';
    exception
    when no_data_found then
      select prod_id into temp_prod_id from products p
       where p.version = prod_version
         and p.pgid = v_rec.pgid
         and p.flag = 'N';
  -- this assumes there's always an 'N' record if not wrap this select with exception handling.
    end;

    update items i set i.prod_id = temp_prod_id
    where items.id = v_rec.id;
    commit;
  end loop;
end;