如何在不使用 GROUP BY 或 PARTITION BY 的情况下对 Oracle SQL 中的数据进行分组
Posted
技术标签:
【中文标题】如何在不使用 GROUP BY 或 PARTITION BY 的情况下对 Oracle SQL 中的数据进行分组【英文标题】:How do I group data in Oracle SQL without using GROUP BY OR PARTITION BY 【发布时间】:2021-04-06 22:23:12 【问题描述】:我的数据是这样的
MY_TABLE
DATE | CUSTOMER_ID | FAC_NUM | MONIES |
---|---|---|---|
01/Jan/2020 | 12345678 | ABC123 | 125000 |
02/Jan/2020 | 12345678 | ABC123 | 125000 |
03/Jan/2020 | 12345678 | ABC123 | 125000 |
01/Feb/2020 | 12345678 | ABC123 | 143000 |
02/Feb/2020 | 12345678 | ABC123 | 143000 |
03/Feb/2020 | 12345678 | ABC123 | 143000 |
04/Feb/2020 | 12345678 | ABC123 | 143000 |
05/Feb/2020 | 12345678 | ABC123 | 143000 |
01/Mar/2020 | 12345678 | ABC123 | 125000 |
02/Mar/2020 | 12345678 | ABC123 | 125000 |
03/Mar/2020 | 12345678 | ABC123 | 125000 |
04/Mar/2020 | 12345678 | ABC123 | 125000 |
我希望输出是这样的
CUSTOMER_ID | FAC_NUM | MONIES | START_DATE | END_DATE |
---|---|---|---|---|
12345678 | ABC123 | 125000 | 01/Jan/2020 | 03/JAN/2020 |
12345678 | ABC123 | 143000 | 01/Feb/2020 | 05/Feb/2020 |
12345678 | ABC123 | 125000 | 01/Mar/2020 | 04/Mar/2020 |
我尝试过使用以下
SELECT CUSTOMER_ID
,FAC_NUM
,MONIES
,MIN(DATE) AS START_DATE
,MAX(DATE) AS END_DATE
FROM MY_TABLE
GROUP BY CUSTOMER_ID
,FAC_NUM
,MONIES
但是,我用这种方法得到的输出如下(这不是想要的输出)
CUSTOMER_ID | FAC_NUM | MONIES | START_DATE | END_DATE |
---|---|---|---|---|
12345678 | ABC123 | 125000 | 1 Jan 2020 | 4 Mar 2020 |
12345678 | ABC123 | 143000 | 1 Feb 2020 | 5 Feb 2020 |
有没有办法在不使用 PL/SQL 的情况下获得我正在寻找的输出(我需要在一个巨大的数据集上运行这个查询)?如果不是,那么使用 PL/SQL 执行此操作的最有效方法是什么?
我是 *** 和 SQL 的新手。非常感谢您的支持。
提前感谢您的帮助。
问候, 阿尼
【问题讨论】:
【参考方案1】:如果你描述你想要什么,而不是“我想要输出”,它可能会有所帮助。
在我看来,您似乎还想按月另外分组,例如您的查询稍作修改:
SELECT CUSTOMER_ID
,FAC_NUM
,MONIES
,MIN(DATE) AS START_DATE
,MAX(DATE) AS END_DATE
FROM MY_TABLE
GROUP BY CUSTOMER_ID
,FAC_NUM
,MONIES
, to_char(date, 'yyyymm') --> this
当然,date
列名无效;它是为date
数据类型保留的,所以我认为它实际上命名不同。
【讨论】:
我相信你可以使用DATE
作为列名,如果它每次使用都被引用。
当然,@Bob。但你可以做到这一点并不意味着你应该做到这一点。此外,在 OP 的消息中,没有证据表明他们使用了双引号。【参考方案2】:
这听上去像是一个孤岛问题。岛是具有相同客户、面数和金额的相邻行。每当数量发生变化时,就会开始一个新的组。
这是一种使用行号之间的差异来识别岛屿的方法:
select customer_id, fac_num, monies,
min(date) as start_date, max(date) as end_date
from (
select t.*,
row_number() over(partition by customer_id, fac_num order by date) as rn1,
row_number() over(partition by customer_id, fac_num, monies order by date) as rn2
from mytable t
) t
group by customer_id, fac_num, monies, rn1 - rn2
order by customer_id, fac_num, min(start_date)
【讨论】:
谢谢@GMB。这个解决方案解决了这个问题。 当有两个连续的岛屿具有相同的新货币时,此解决方案不起作用。在这种情况下,它将两个岛视为一个。有没有办法解决这个问题?以上是关于如何在不使用 GROUP BY 或 PARTITION BY 的情况下对 Oracle SQL 中的数据进行分组的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 Group By / 有函数的情况下过滤 SQL 中的数据
我可以在不存储 group by 和 order by value 的情况下加快此查询吗?
SQL 查询 - 如何使用 group by 获取 2 行或更多行