oracle如何选择不同的记录?

Posted

技术标签:

【中文标题】oracle如何选择不同的记录?【英文标题】:how to select distinct records in oracle? 【发布时间】:2020-05-18 22:48:22 【问题描述】:

我想在某些条件下选择不同的行,但是当我在 select 语句中添加 id 列时,它会返回所有行???

下面的查询工作正常

select distinct dst_bnk_acnt_id
,dst_cust_id
,org_cust_id
,dst_pos_id
,pmt_typ_cd 
from tb_cm_t_pmt_coll
where org_pos_id = 8 OR dst_pos_id = 8 OR dst_bnk_acnt_id = 1 ;

但是当我想使用 order by id(desc) 选择最新记录时,它会返回所有行!

SELECT  distinct id
,dst_bnk_acnt_id
,dst_cust_id
,org_cust_id
,dst_pos_id
,pmt_typ_cd  
FROM  tb_cm_t_pmt_coll
WHERE org_pos_id = 8 OR dst_pos_id = 8 OR dst_bnk_acnt_id = 1 
ORDER BY id DESC;

我知道 'id' 列是主键,它的所有值都是唯一的,因此所有行都变得唯一。

我只想使用这些 [dst_bnk_acnt_id,dst_cust_id,org_cust_id,dst_pos_id,pmt_typ_cd] 列选择不同的行,但我也想使用 id 以降序排列它们。

请帮忙。

【问题讨论】:

结果中需要id吗? 如果您只想按 id 对结果进行排序,您可以不将 id 放入选择列表中。 不,我不想在结果中出现 id。 @krishnPatel 你能告诉我怎么做吗 不能有不包含 ID 的唯一值,同时按 ID 排序。我想您必须找到包含在唯一列列表中的列进行排序。 【参考方案1】:

我没有你的表,所以我将使用 Scott 的示例架构。

不同的部门和工作是:

SQL> select distinct deptno, job from emp;

    DEPTNO JOB
---------- ---------
        20 CLERK
        30 SALESMAN
        20 MANAGER
        30 CLERK
        10 PRESIDENT
        30 MANAGER
        10 CLERK
        10 MANAGER
        20 ANALYST

9 rows selected.

我们希望根据EMPNO(类似于您的ID)对数据进行排序:

SQL> select distinct deptno, job from emp order by empno;
select distinct deptno, job from emp order by empno
                                              *
ERROR at line 1:
ORA-01791: not a SELECTed expression


SQL>

它不起作用(正如您已经知道的那样)。但是,如果您使用子查询(或 CTE),那么您会得到:

SQL> with temp as
  2    (select min(empno) id, deptno, job
  3     from emp
  4     group by deptno, job
  5     order by 1 desc
  6    )
  7  select deptno, job
  8  From temp
  9  order by id desc;

    DEPTNO JOB
---------- ---------
        10 CLERK
        30 CLERK
        10 PRESIDENT
        20 ANALYST
        10 MANAGER
        30 MANAGER
        20 MANAGER
        30 SALESMAN
        20 CLERK

9 rows selected.

SQL>

这意味着您的查询可能如下所示:

WITH temp
     AS (  SELECT MIN (id) id,
                  dst_bnk_acnt_id,
                  dst_cust_id,
                  org_cust_id,
                  dst_pos_id,
                  pmt_typ_cd
             FROM tb_cm_t_pmt_coll
            WHERE    org_pos_id = 8
                  OR dst_pos_id = 8
                  OR dst_bnk_acnt_id = 1
         GROUP BY dst_bnk_acnt_id,
                  dst_cust_id,
                  org_cust_id,
                  dst_pos_id,
                  pmt_typ_cd)
  SELECT dst_bnk_acnt_id,
         dst_cust_id,
         org_cust_id,
         dst_pos_id,
         pmt_typ_cd
    FROM temp
ORDER BY id DESC;

【讨论】:

【参考方案2】:

我会为此使用窗口函数:

select id,
       dst_bnk_acnt_id,
       dst_cust_id, 
       org_cust_id,
       dst_pos_id,
       pmt_typ_cd
FROM (
  SELECT id,
         dst_bnk_acnt_id,
         dst_cust_id, 
         org_cust_id,
         dst_pos_id,
         pmt_typ_cd, 
         row_number() over (partition by dst_bnk_acnt_id,dst_cust_id,org_cust_id,dst_pos_id,pmt_typ_cd 
                            order by id desc) as rn  
  FROM  tb_cm_t_pmt_coll
  WHERE org_pos_id = 8 
     OR dst_pos_id = 8 
     OR dst_bnk_acnt_id = 1 
)  
WHERE rn = 1
ORDER BY id;

窗口函数中的order by id desc 将具有最高id 的行设为行号1,为不同列的每个组合选择最新的id

【讨论】:

以上是关于oracle如何选择不同的记录?的主要内容,如果未能解决你的问题,请参考以下文章

如何连接具有选择性重复记录的表? (oracle10g)

Oracle如何快速选择和更新一个字段值并插入记录

从 Oracle 中选择最新的两条不同记录

如何使用 Oracle.ManagedDataAccess.EntityFramework 提供程序从不同的架构中选择表?

如何在 Oracle SQL 中选择上个月登录并在 8 月之前的一个月中记录最少 1 次的行?

Oracle:根据不同列的值选择不同的列