【问题标题】:How do I group data in Oracle SQL without using GROUP BY OR PARTITION BY如何在不使用 GROUP BY 或 PARTITION BY 的情况下对 Oracle SQL 中的数据进行分组
【发布时间】: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 执行此操作的最有效方法是什么?

我是 stackoverflow 和 SQL 的新手。非常感谢您的支持。

提前感谢您的帮助。

问候, 阿尼

【问题讨论】:

    标签: sql oracle datetime aggregate-functions gaps-and-islands


    【解决方案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。这个解决方案解决了这个问题。
    • 当有两个连续的岛屿具有相同的新货币时,此解决方案不起作用。在这种情况下,它将两个岛视为一个。有没有办法解决这个问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    相关资源
    最近更新 更多