【问题标题】:How to use GREATEST function with Over Partition by in Oracle如何在 Oracle 中将 GREATEST 函数与 Over Partition by 一起使用
【发布时间】:2023-01-29 23:03:41
【问题描述】:

在下面的代码中,我想选择 customer_name、位置、性别和地址以及 customerid、aread_code。

select 
    customerid, aread_code, GREATEST(MAX(productid), MAX(itemid))
from   
    CUSTOMER C 
inner join 
    ORDER O ON c.custid = o.custid
where  
    c.custtype = 'EXECUTIVE'
group 
    customerid, by aread_code;

我尝试使用 GREATEST 函数和 OVER PARTITION BY 来显示所需的列。它抛出一个错误。

您能帮我选择所需的列吗?

谢谢你。

【问题讨论】:

  • 您当前的查询有什么问题(看起来正确),为什么认为您需要在这里使用 GREATEST() 作为分析函数?
  • 我想得到 MAX(C.productid) 或 MAX(O.itemid) 哪个最高。连同输出中需要的 customer_name、location、gener、address、customerid 和 aread_code。
  • 您当前的查询对我来说看起来完全有效。
  • 可能是我们不太明白你想要什么。请提供示例数据和所需结果(基于该示例)。
  • 我想获得 MAX(C.productid) 或 MAX(O.itemid),对于每个 cusromerid 和 area_code 组合,哪个最高。连同输出中需要的 customer_name、location、gener、address、customerid 和 aread_code。

标签: oracle oracle11g


【解决方案1】:

免责声明:

当处理多个表时,用它们的表名限定列。您还没有这样做,所以我们不知道 aread_code 所在的两个表中的哪一个。在我的回答中,我假设它是客户的区域。如果不是,那么您需要一个不同的答案。

回答:

您按 customer_id 和区号分组。这为每个客户提供一行。并且您想要订单表中的最大产品/项目 ID。 (我想它们是从同一个序列中抽取的,所以你可以使用这个 ID 以某种方式从那里继续。)

最简单的方法是在子查询中获取最大 ID。直接在 select 子句中或在 from 子句中。

以下是如何在 SELECT 子句中执行此操作:

select
  c.*,
  (
    select greatest(max(productid), max(itemid))
    from orders o
    where o.custid = c.custid
  ) as max_id
from customer c 
where c.custtype = 'EXECUTIVE';

这是在 FROM 子句中执行此操作的一种方法:

select
  c.*,
  agg.max_id
from customer c 
outer apply
(
  select greatest(max(productid), max(itemid)) as max_id
  from orders o
  where o.custid = c.custid
) agg
where c.custtype = 'EXECUTIVE';

这是在 FROM 子句中执行此操作的另一种方法:

select
  c.*,
  agg.max_id
from customer c 
left outer join
(
  select
    custid,
    greatest(max(productid), max(itemid)) as max_id
  from orders
  group by custid
) agg on agg.custid = c.custid
where c.custtype = 'EXECUTIVE';

如果您只希望客户至少有一个订单,那么我推荐使用 FROM 子句的方法。您必须将 OUTER APPLY 变成 CROSS APPLY resp。为此,LEFT OUTER JOIN 变成了INNER JOIN

【讨论】:

    【解决方案2】:

    您的代码中有几个错误。主要的混淆是没有为列使用表别名前缀。有一个错误的组,你的表名 ORDER 有问题 - 如果它是一个表的名称。 ORDER 是 Oracle 中的保留字,如果它是表的名称,那么您应该使用类似“YOUR_OWNER_NAME”、“ORDER”之类的名称。这是带有一些示例数据和结果的核心代码:

    WITH 
        customers  (CUSTID, PRODUCTID, AREAD_CODE, CUSTOMER_NAME, LOCATION, GENDER, ADDRESS, CUSTTYPE)  AS
            (
                Select 1, 1, 63,  'Name 1', 'Location 1', 'M', 'Address 1', 'EXECUTIVE' From Dual Union All
                Select 2, 1, 63,  'Name 1', 'Location 1', 'M', 'Address 1', 'EXECUTIVE' From Dual Union All
                Select 3, 3, 63,  'Name 1', 'Location 1', 'M', 'Address 1', 'EXECUTIVE' From Dual Union All
                Select 4, 7, 63,  'Name 1', 'Location 1', 'M', 'Address 1', 'EXECUTIVE' From Dual           
            ),
        orders (ORDER_ID, CUSTID, ITEMID, SOME_COLUMN)  AS
            (
                Select 1, 1, 1, 'Some other data' From Dual Union All
                Select 2, 2, 1, 'Some other data' From Dual Union All
                Select 3, 3, 1, 'Some other data' From Dual Union All
                Select 4, 3, 3, 'Some other data' From Dual Union All
                Select 5, 4, 1, 'Some other data' From Dual Union All
                Select 6, 4, 8, 'Some other data' From Dual 
            )
    
    select 
        c.custid, c.aread_code, GREATEST(MAX(c.productid), MAX(o.itemid)) "MAX_ID"
    from   
        CUSTOMERS C 
    inner join 
        ORDERS O ON c.custid = o.custid
    where  
        c.custtype = 'EXECUTIVE'
    group by
        c.custid, c.aread_code
    
        CUSTID AREAD_CODE     MAX_ID
    ---------- ---------- ----------
             1         63          1 
             4         63          8 
             3         63          3 
             2         63          1
    

    根据您可以使用其中部分或全部的实际数据,有不同的选项来获取其余列。

    选项 1 - 按照下面 Beefstu 的评论中的建议进行选择和分组

    select Distinct
        c.custid, c.customer_name, c.location, c.address, c.gender, c. custtype, c.aread_code, 
        GREATEST(MAX(c.productid), MAX(o.itemid)) "MAX_ID"
    from   
        CUSTOMERS C 
    inner join 
        ORDERS O ON c.custid = o.custid
    where  
        c.custtype = 'EXECUTIVE'
    group by
        c.custid, c.customer_name, c.location, c.address, c.gender, c. custtype, c.aread_code
    order  by c.custid
    
    
        CUSTID CUSTOMER_NAME LOCATION   ADDRESS   GENDER CUSTTYPE  AREAD_CODE     MAX_ID
    ---------- ------------- ---------- --------- ------ --------- ---------- ----------
             1 Name 1        Location 1 Address 1 M      EXECUTIVE         63          1 
             2 Name 1        Location 1 Address 1 M      EXECUTIVE         63          1 
             3 Name 1        Location 1 Address 1 M      EXECUTIVE         63          3 
             4 Name 1        Location 1 Address 1 M      EXECUTIVE         63          8
    

    选项 2. - 使用带有 Distinct 关键字的分析函数 MAX() OVER() (对于大数据集可能会导致性能成本高) - 结果与上面相同

    select Distinct
        c.custid, c.customer_name, c.location, c.address, c.gender, c. custtype, c.aread_code, 
        GREATEST(MAX(c.productid) OVER(Partition By c.custid), MAX(o.itemid) OVER(Partition By c.custid)) "MAX_ID"
    from   
        CUSTOMERS C 
    inner join 
        ORDERS O ON c.custid = o.custid
    where  
        c.custtype = 'EXECUTIVE'
    order  by c.custid
    

    选项 3 - 使用左连接到子查询 - 请参阅 Thorsten Kettner 提供的解决方案

    【讨论】:

    • 感谢您的代码。我想显示所有这些列 customer_name、location、gender、address、customerid 和 aread_code。但我们应该只按 customerid 和 aread_code 分组。
    • 无论您想显示什么其他信息,请添加到 SELECT 和 group by 语句中。 group by order要匹配SELECT语句 7
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 2013-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    相关资源
    最近更新 更多