sql - How can I create a View in Oracle with a String column whose content is aggregated from numeric values of related entities?
问题描述
In a Java application based on an Oracle SQL database, I have the following problem to solve:
An entity DataDelivery
can consist of any number of Packet
.
Packet
has a ReportDate
and the the foreign key datadeliveryid
.
ReportDate
is of Datatype NUMBER(4,0) and contains the year (YYYY) for example 2020, or 2018. The column ReportDate
is in in table PACKET.
In my view, I want to display the DataDelivery
as table rows including a column that displays the combined report date (YYYY) of all pertaining packets.
The combined ReportDate of the Packets shall be a comma separated list.
Important: When a year such as '2018' occurs multiple times, it shall not be repeated.
So, a DataDelivery with 3 Packets as follows:
DataDelivery
PACKET1, ReportDate:2020
PACKET2, ReportDate:2020
PACKET3, ReportDate:2018
PACKET4, ReportDate: `null`
shall be displayed as: 2018, 2020
That means, null
must be ignored, 2020 must not be repeated.
And the values must be sorted in ascending order.
If all packets have a null value as ReportDate, the value in the view must be empty.
For simplicity's sake, I ommitted some of the complexity of my problem including several joins, etc. Also, the dates can only be 2018
, 2020
, or null
, although it would be nicer to remove this constraint. Perhaps someone can suggest a solution based on what I tried here:
CASE
WHEN COUNT(CASE eqpaket.berichtszeitraum WHEN 2020 THEN 2020 END) = COUNT(*) THEN '2020'
WHEN COUNT(CASE eqpaket.berichtszeitraum WHEN 2018 THEN 2018 END) = COUNT(*) THEN '2018'
WHEN COUNT(distinct eqpaket.berichtszeitraum) > 1 THEN
listagg(eqpaket.berichtszeitraum, ',') within group(order by datenlieferungid)
ELSE ''
END AS berichtszeitraum,
This works great, when all ReportDates are the same. When they differ, I get duplicates. In the example above I would get: 2018, 2020, 2020
. Those duplicates need to be removed, and this must happen within the CASE -- END, if I stick to this approach.
解决方案
分两步进行(因为您的数据库版本不支持listagg
with distinct
):
SQL> with datedelivery (datedeliveryid, packet, reportdate) as
2 -- sample data
3 (select 1, 'packet1', 2020 from dual union all
4 select 1, 'packet2', 2020 from dual union all
5 select 1, 'packet3', 2018 from dual union all
6 select 1, 'packet4', null from dual union all
7 --
8 select 2, 'packet5', 2017 from dual union all
9 select 2, 'packet6', 2017 from dual union all
10 select 2, 'packet7', null from dual
11 )
12 -- query you need
13 select datedeliveryid,
14 listagg(reportdate, ', ') within group (order by reportdate) years
15 from (-- first find DISTINCT values, then aggregate them
16 select distinct datedeliveryid, reportdate
17 from datedelivery
18 )
19 group by datedeliveryid;
DATEDELIVERYID YEARS
-------------- --------------------
1 2018, 2020
2 2017
SQL>
推荐阅读
- e2e-testing - 赛普拉斯测试机构
- sql - 如何按日期分组并按日期持续时间求和两个时间戳?
- android - 将指定类扩展为函数中的参数的任何对象
- angular - 悬停时在amcharts 4中堆叠单列
- node.js - 如何在Nodejs(微服务)中将大量数据(100万大小的对象数组)从一个服务发送到另一个服务?
- python - 计算概率描述性统计的正确方法
- wordpress - 如何检查自定义字段是否具有特定值
- json - 单击父级时如何仅显示嵌套元素?- 反应
- c - 为什么这个不区分大小写的 strstr() 函数版本不起作用?
- angular - waitForAngularEnable(true) 不起作用 - ScriptTimeoutError:脚本超时:未收到结果