如何 select 每个组的前 5 个日期并将它们放在 Oracle 中用逗号分隔的单个列中?
How to select the first 5 dates from each group and put them in a single column separated by comma in Oracle?
我有一个 table 这样的:
Division
Region
Date of Last Visit
1
2
11/20/2021
1
2
11/18/2021
1
7
10/18/2021
1
7
11/19/2021
2
2
11/17/2021
2
3
09/20/2021
2
3
10/20/2021
我想编写一个按部门和地区列分组的查询,并在单个列中为我提供每个组的最后 5 个日期,用逗号分隔。像这样:
Division
Region
Date of Last Visit
Today
Days since last visit
1
2
11/20/2021, 11/18/2021
sysdate
sysdate - max(date of last visit)
1
7
10/18/2021, 11/19/2021
sysdate
sysdate - max(date of last visit)
2
2
11/17/2021
sysdate
sysdate - max(date of last visit)
2
3
9/20/2021, 10/20/2021
sysdate
sysdate - max(date of last visit)
最后两列是自定义计算列,我也需要它们作为最终输出 table。任何帮助将不胜感激,因为我已经尝试了很多事情,但我不断收到关于它没有正确分组的错误,可能是因为最后有两个额外的列。但即使没有它,我也不确定如何在 oracle 中只获取每组的最后 5 个日期。
谢谢!
给你;阅读代码中的注释。
SQL> with test (division, region, datum) as
2 -- sample data
3 (select 1, 2, date '2021-11-20' from dual union all
4 select 1, 2, date '2021-11-18' from dual union all
5 select 1, 7, date '2021-10-18' from dual union all
6 select 1, 7, date '2021-11-19' from dual union all
7 select 2, 2, date '2021-11-17' from dual union all
8 select 2, 3, date '2021-09-20' from dual union all
9 select 2, 3, date '2021-10-20' from dual
10 ),
11 temp as
12 -- rank rows per division/region, sorted by date column in descending order
13 (select t.*,
14 rank() over (partition by division, region order by datum desc) rnk
15 from test t
16 )
17 -- select up to 5 last rows per division/region
18 select division, region,
19 listagg(datum, ', ') within group (order by datum) dates,
20 trunc(sysdate) today,
21 --
22 (select trunc(sysdate) - a.datum
23 from temp a
24 where a.division = t.division
25 and a.region = t.region
26 and a.rnk = 1) days_since
27 from temp t
28 where rnk <= 5
29 group by division, region
30 order by division, region;
DIVISION REGION DATES TODAY DAYS_SINCE
---------- ---------- ------------------------------ ---------- ----------
1 2 11/18/2021, 11/20/2021 11/30/2021 10
1 7 10/18/2021, 11/19/2021 11/30/2021 11
2 2 11/17/2021 11/30/2021 13
2 3 09/20/2021, 10/20/2021 11/30/2021 41
SQL>
您想使用 ROW_NUMBER
分析函数过滤最大的每组 n,然后聚合:
SELECT division,
region,
LISTAGG(TO_CHAR(date_of_last_visit, 'DD/MM/YYYY'), ',')
WITHIN GROUP (ORDER BY date_of_last_visit DESC)
AS date_of_last_visit,
SYSDATE AS today,
TRUNC(SYSDATE - MAX(date_of_last_visit)) AS days_since_last_visit
FROM (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY division, region
ORDER BY date_of_last_visit DESC) AS rn
FROM table_name t
)
WHERE rn <= 5
GROUP BY
division,
region
其中,对于示例数据:
CREATE TABLE table_name (division, region, date_of_last_visit) as
select 1, 2, date '2021-11-20' from dual union all
select 1, 2, date '2021-11-18' from dual union all
select 1, 7, date '2021-10-18' from dual union all
select 1, 7, date '2021-11-19' from dual union all
select 2, 2, date '2021-11-17' from dual union all
select 2, 3, date '2021-09-20' from dual union all
select 2, 3, date '2021-10-20' from dual;
输出:
DIVISION
REGION
DATE_OF_LAST_VISIT
TODAY
DAYS_SINCE_LAST_VISIT
1
2
20/11/2021,18/11/2021
30-NOV-21
10
1
7
19/11/2021,18/10/2021
30-NOV-21
11
2
2
17/11/2021
30-NOV-21
13
2
3
20/10/2021,20/09/2021
30-NOV-21
41
db<>fiddle here
我有一个 table 这样的:
Division | Region | Date of Last Visit |
---|---|---|
1 | 2 | 11/20/2021 |
1 | 2 | 11/18/2021 |
1 | 7 | 10/18/2021 |
1 | 7 | 11/19/2021 |
2 | 2 | 11/17/2021 |
2 | 3 | 09/20/2021 |
2 | 3 | 10/20/2021 |
我想编写一个按部门和地区列分组的查询,并在单个列中为我提供每个组的最后 5 个日期,用逗号分隔。像这样:
Division | Region | Date of Last Visit | Today | Days since last visit |
---|---|---|---|---|
1 | 2 | 11/20/2021, 11/18/2021 | sysdate | sysdate - max(date of last visit) |
1 | 7 | 10/18/2021, 11/19/2021 | sysdate | sysdate - max(date of last visit) |
2 | 2 | 11/17/2021 | sysdate | sysdate - max(date of last visit) |
2 | 3 | 9/20/2021, 10/20/2021 | sysdate | sysdate - max(date of last visit) |
最后两列是自定义计算列,我也需要它们作为最终输出 table。任何帮助将不胜感激,因为我已经尝试了很多事情,但我不断收到关于它没有正确分组的错误,可能是因为最后有两个额外的列。但即使没有它,我也不确定如何在 oracle 中只获取每组的最后 5 个日期。
谢谢!
给你;阅读代码中的注释。
SQL> with test (division, region, datum) as
2 -- sample data
3 (select 1, 2, date '2021-11-20' from dual union all
4 select 1, 2, date '2021-11-18' from dual union all
5 select 1, 7, date '2021-10-18' from dual union all
6 select 1, 7, date '2021-11-19' from dual union all
7 select 2, 2, date '2021-11-17' from dual union all
8 select 2, 3, date '2021-09-20' from dual union all
9 select 2, 3, date '2021-10-20' from dual
10 ),
11 temp as
12 -- rank rows per division/region, sorted by date column in descending order
13 (select t.*,
14 rank() over (partition by division, region order by datum desc) rnk
15 from test t
16 )
17 -- select up to 5 last rows per division/region
18 select division, region,
19 listagg(datum, ', ') within group (order by datum) dates,
20 trunc(sysdate) today,
21 --
22 (select trunc(sysdate) - a.datum
23 from temp a
24 where a.division = t.division
25 and a.region = t.region
26 and a.rnk = 1) days_since
27 from temp t
28 where rnk <= 5
29 group by division, region
30 order by division, region;
DIVISION REGION DATES TODAY DAYS_SINCE
---------- ---------- ------------------------------ ---------- ----------
1 2 11/18/2021, 11/20/2021 11/30/2021 10
1 7 10/18/2021, 11/19/2021 11/30/2021 11
2 2 11/17/2021 11/30/2021 13
2 3 09/20/2021, 10/20/2021 11/30/2021 41
SQL>
您想使用 ROW_NUMBER
分析函数过滤最大的每组 n,然后聚合:
SELECT division,
region,
LISTAGG(TO_CHAR(date_of_last_visit, 'DD/MM/YYYY'), ',')
WITHIN GROUP (ORDER BY date_of_last_visit DESC)
AS date_of_last_visit,
SYSDATE AS today,
TRUNC(SYSDATE - MAX(date_of_last_visit)) AS days_since_last_visit
FROM (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY division, region
ORDER BY date_of_last_visit DESC) AS rn
FROM table_name t
)
WHERE rn <= 5
GROUP BY
division,
region
其中,对于示例数据:
CREATE TABLE table_name (division, region, date_of_last_visit) as
select 1, 2, date '2021-11-20' from dual union all
select 1, 2, date '2021-11-18' from dual union all
select 1, 7, date '2021-10-18' from dual union all
select 1, 7, date '2021-11-19' from dual union all
select 2, 2, date '2021-11-17' from dual union all
select 2, 3, date '2021-09-20' from dual union all
select 2, 3, date '2021-10-20' from dual;
输出:
DIVISION REGION DATE_OF_LAST_VISIT TODAY DAYS_SINCE_LAST_VISIT 1 2 20/11/2021,18/11/2021 30-NOV-21 10 1 7 19/11/2021,18/10/2021 30-NOV-21 11 2 2 17/11/2021 30-NOV-21 13 2 3 20/10/2021,20/09/2021 30-NOV-21 41
db<>fiddle here