如何在 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_rank
或 row_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
;
架构和插入语句:
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
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_rank
或 row_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
;
架构和插入语句:
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