如何在不使用 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 子句的情况下对行进行分组

如何在不使用 Group By / 有函数的情况下过滤 SQL 中的数据

我可以在不存储 group by 和 order by value 的情况下加快此查询吗?

SQL 查询 - 如何使用 group by 获取 2 行或更多行

使用 dplyr、group_by 和折叠或汇总连接字符串/行,但保持 NA 值 [重复]

使用 CTE 在 Group by 之前或之后过滤