ORACLE:如何只用1列获得GROUP的所有列?

时间:2017-01-18 03:12:40

标签: oracle

我正在使用ORACLE数据库, 如何使用GROUP只有1列(EMP_ID)获取所有列?

示例我有表ESD_RESULTS

FIRST_NAME | LAST_NAME | EMP_ID | WRIST_STATUS | LFOOT_STATUS | DATE
Dodo       | A         | 0101   | Pass         | Pass         | 2016-01-18 10:00
Wedi       | Wil       | 0105   | Pass         | Pass         | 2016-01-18 10:05
Dodo       | A         | 0101   | Pass         | Fail         | 2016-01-18 10:11

我想要的数据显示是(如果EMP_ID相同,则按日期desc获取最后一个数据):

FIRST_NAME | LAST_NAME | EMP_ID | WRIST_STATUS | LFOOT_STATUS | DATE
Dodo       | A         | 0101   | Pass         | Fail         | 2016-01-18 10:11
Wedi       | Wil       | 0105   | Pass         | Pass         | 2016-01-18 10:05

我尝试使用DISTINCT和GROUP,数据仍显示全部。

2 个答案:

答案 0 :(得分:4)

一种选择是使用ROW_NUMBER()来识别每位员工的最新记录:

SELECT t.FIRST_NAME,
       t.LAST_NAME,
       t.EMP_ID,
       t.WRIST_STATUS,
       t.LFOOT_STATUS,
       t.DATE
FROM
(
    SELECT FIRST_NAME, LAST_NAME, EMP_ID, WRIST_STATUS, LFOOT_STATUS, DATE,
           ROW_NUMBER() OVER (PARTITION BY EMP_ID ORDER BY DATE DESC) rn
    FROM ESD_RESULTS
) t
WHERE t.rn = 1

答案 1 :(得分:2)

由于大概的名字和姓氏是由emp_id决定的(他们不会从一行变为另一行),所以你可以将所有三列分组 - 从而减少工作量。 (另一方面,规范化表格设计会更有意义;一个表格显示每个emp_id的关联名字和姓氏,不需要在&#34中重复名字和姓氏;这个&# 34;表格,你在帖子中显示。)

然后:您可以使用FIRST / LAST函数,使用keep(dense_rank ...),如下所示,以消除对子查询和外部查询的需要。如果有两行具有完全相同的emp_id日期和时间,您可以优化查询以适应"打破"某种。如果没有联系,那么查询将无需修改即可运行。

DATE是Oracle中的保留字,不应该用于表名或列名。我将其更改为DT

with
     test_data ( first_name, last_name, emp_id, wrist_status, lfoot_status, dt ) as (
       select 'Dodo', 'A'  , 0101, 'Pass', 'Pass', to_date('2016-01-18 10:00', 'yyyy-mm-dd hh24:mi') from dual union all
       select 'Wedi', 'Wil', 0105, 'Pass', 'Pass', to_date('2016-01-18 10:05', 'yyyy-mm-dd hh24:mi') from dual union all
       select 'Dodo', 'A'  , 0101, 'Pass', 'Fail', to_date('2016-01-18 10:11', 'yyyy-mm-dd hh24:mi') from dual
     )
-- end of test data (NOT part of the solution); SQL query begins BELOW THIS LINE
select   first_name, last_name, emp_id,
         min(wrist_status) keep (dense_rank last order by dt) as wrist_status,
         min(lfoot_status) keep (dense_rank last order by dt) as lfoot_status,
         max(dt) as dt
from     test_data
group by first_name, last_name, emp_id
;

FIRST_NAME LAST_NAME     EMP_ID WRIST_STATUS LFOOT_STATUS DT
---------- --------- ---------- ------------ ------------ ----------------
Dodo       A                101 Pass         Fail         2016-01-18 10:11
Wedi       Wil              105 Pass         Pass         2016-01-18 10:05

2 rows selected.
相关问题