如何在 Oracle 中使用 Having 和 Group By 和 Order By?

How to use Having with Group By and Order By in Oracle?

SELCT * FROM MyTable;

ID    Status            posted_date       posted_by
---------------------------------------------------
0      invalid          01/01/2021         abc
1      in-progress      02/01/2021         xyz
0      invalid          03/01/2021         lmn
2      complete         04/01/2021         pqr
1      in-progress      05/01/2021         newton
2      complete         06/01/2021         einstein
2      complete         07/01/2021         jack

我需要按 ID 分组。 然后按 posted_date 降序排列。 然后找出发布最新交易的用户。

在这种情况下,我的预期输出是,

ID    Status            posted_date       posted_by
---------------------------------------------------
2      complete          07/01/2021        jack
1      in-progress       05/01/2021        newton
0      invalid           03/01/2021        lmn

下面是我试过的。我没有得到任何行。

SELECT COUNT(ID), ID, status, posted_by,posted_date
FROM MyTable
GROUP BY ID, status, posted_by,posted_date
HAVING COUNT(ID) > 1
ORDER BY posted_date DESC;

你的问题是获取最大日期的行,你有几种方法可以获取它

SELECT ID, status, posted_by, posted_date
FROM MyTable
WHERE (id, posted_date) IN 
    (
        SELECT id, MAX(posted_date)
        FROM MyTable
        GROUP BY id
    )
ORDER BY id;

使用 JOIN

SELECT t.ID, t.status, t.posted_by, t.posted_date
FROM MyTable t
INNER JOIN 
(
    SELECT id, MAX(posted_date) AS max_posted_date
    FROM MyTable
    GROUP BY id
) m
ON t.id = m.id AND t.posted_date = m.max_posted_date
ORDER BY t.id;

或使用解析函数

SELECT *
FROM 
(
    SELECT ID, status, posted_by, posted_date,
        ROW_NUMBER() OVER (PARTITION BY id ORDER by posted_date DESC) AS rn
    FROM MyTable
)
WHERE rn = 1 
ORDER BY id;

您似乎不想使用聚合函数。看起来您想使用 window 函数。像这样(使用 dense_rankrow_number 而不是 rank 取决于你想如何处理关系)

with ranked_data as (
  select t.*,
         rank() over (partition by id 
                          order by posted_date desc) rnk
    from yourTable t
)
select *
  from ranked_data
 where rnk = 1

您也可以使用 keep dense_rank 聚合子句来做到这一点。

select ID
, max(STATUS)keep(dense_rank first order by POSTED_DATE desc) STATUS
, max(POSTED_DATE)keep(dense_rank first order by POSTED_DATE desc)POSTED_DATE
, max(POSTED_BY)keep(dense_rank first order by POSTED_DATE desc)POSTED_BY
from myTable t
group by ID
order by ID desc
;

demo

架构和插入语句:

 create table MyTable(ID int, Status varchar(100), posted_date date, posted_by varchar(50));

 insert into MyTable values(0, 'invalid',          date'2021-01-01','abc');
 insert into MyTable values(1, 'in-progress',      date'2021-01-02','xyz');
 insert into MyTable values(0, 'invalid',          date'2021-01-03','lmn');
 insert into MyTable values(2, 'complete',         date'2021-01-04','pqr');
 insert into MyTable values(1, 'in-progress',      date'2021-01-05','newton');
 insert into MyTable values(2, 'complete' ,        date'2021-01-06','einstein');
 insert into MyTable values(2, 'complete',         date'2021-01-07','jack');

查询:

 with cte as
 (
   select ID,Status,posted_date,posted_by,
   row_number()over(partition by id order by posted_date desc) as rn
   from MyTable
 )
 select ID,Status,posted_date,posted_by from cte where rn=1 
 order by posted_date desc

输出:

ID STATUS POSTED_DATE POSTED_BY
2 complete 07-JAN-21 jack
1 in-progress 05-JAN-21 newton
0 invalid 03-JAN-21 lmn

db<>fiddle here