简体   繁体   English

使用 sum 时避免使用 group by

[英]Avoid to use group by when using sum

I'm new to SQL/ORACLE .我是SQL/ORACLE新手。 I am trying to wrote a query to get the desired result.我正在尝试编写一个查询以获得所需的结果。 I am using a sum function also in the select statement bu then I also have to write all columns from select in the group by clause.我也在 select 语句中使用 sum 函数,然后我还必须在group by子句中写入select中的所有列。 Is there any way to avoid using this approach.有什么办法可以避免使用这种方法。 Below is my query and it is giving me the desired result, I just want to get rid of group by clause.下面是我的查询,它给了我想要的结果,我只想摆脱group by子句。

SELECT
    T1.ORDER_CODE "ORDER NUMBER",
    T1.ORDER_ITEM "ORDER ITEM",
    T1.ROLL_SHEET,
    T1.ORDER_STATUS "ORDER ITEM STATUS",
    T1.ORDER_TYPE "ORDER_TYPE",
    T2.ORDER_STATUS_SALES "SALES ORDER STATUS",
    T1.CLASSIFICATION "GRADE",
    T1.PRODUCT_CODE "PRODUCT", 
    T1.ARTICLE_CODE "ARTICLE",
    T1.WIDTH || 'x' || T1.LENGTH || 'x' || NVL((NULLIF(T1.HEIGHT_PALLET,0)),T1.DIAMETER) "SIZE", 
    T2.DATE_CUST_ISSUED "ORDERED DATE", 
    T2.DATE_CONFIRMED "CONFIRMATION DATE",
    T1.DATE_EXMILL "EXMILL DATE",
    T1.MASS_ORDERED "ORDERED",
    T3.MASS_TRIMMED "TRIMMED", 
    T3.MASS_WOUND "PRODUCED",
    T3.MASS_SCALED "WRAPPED",
    SUM(T4.MASS) "IN WH"
FROM ORDERITEM T1 
INNER JOIN ORDERHEADER T2 ON T1.ORDER_CODE = T2.ORDER_CODE
LEFT OUTER JOIN MACHINERUNORDERITEM T3 ON T1.ORDER_CODE = T3.ORDER_CODE AND T1.ORDER_ITEM = T3.ORDER_ITEM
LEFT OUTER JOIN ORDERITEMINVENTORY T4 ON T1.ORDER_CODE = T4.ORDER_CODE AND T1.ORDER_ITEM = T4.ORDER_ITEM
WHERE T1.ORDER_CODE = '1000000294'
GROUP BY T1.ORDER_CODE, T1.ORDER_ITEM, T1.ROLL_SHEET, T1.ORDER_STATUS,
         T1.ORDER_TYPE, T2.ORDER_STATUS_SALES, T1.CLASSIFICATION,
         T1.PRODUCT_CODE, T1.ARTICLE_CODE,
         T1.WIDTH || 'x' || T1.LENGTH || 'x' || NVL((NULLIF(T1.HEIGHT_PALLET,0)),T1.DIAMETER),
         T2.DATE_CUST_ISSUED, T2.DATE_CONFIRMED, T1.DATE_EXMILL,
         T1.MASS_ORDERED, T3.MASS_TRIMMED, T3.MASS_WOUND, T3.MASS_SCALED

Well, you can't.嗯,你不能。 It's part of the SYNTAX.它是 SYNTAX 的一部分。

If you use SUM, SQL, which thinks in sets (not line by line), must have a GROUP BY clause.如果使用 SUM,则以集合(而不是逐行)进行思考的 SQL 必须具有 GROUP BY 子句。 When you ask for a column in the SELECT statement, SQL (Oracle, in this case), brings you the columns.当您在 SELECT 语句中请求一列时,SQL(在本例中为 Oracle)会为您提供这些列。 If you want to SUM, it need to know what to GROUP BY, otherwise, it would just SUM everything.如果你想求和,它需要知道要 GROUP BY 的内容,否则,它只会对所有内容求和。 That's all.就这样。 I suggest you'd read more about the GROUP BY clause and the SUM function in the W3 schools in order to understand the issue better.我建议您阅读有关W3 学校中的 GROUP BY 子句和 SUM 函数的更多信息,以便更好地理解该问题。

A typicall way of constructing a non-trivial GROUP BY statement is to write the first part and copy the grouping columns in the GROUP BY clause构建非平凡GROUP BY语句的典型方法是编写第一部分并复制GROUP BY子句中的分组列

select 
COL1 ||'-' || COL2 as x,
case when COL1 = 'A1' then COL2 ||'-' || COL1 else COL1 || '-' || COL2 end as y,
sum(COL3)
from tab
group by COL1 ||'-' || COL2 as x,
case when COL1 = 'A1' then COL2 ||'-' || COL1 else COL1 || '-' || COL2 end as y;

This leads to an error:这会导致错误:

ORA-00933: SQL command not properly ended

and is known pain point (interestingly not for all) - see the discussion in Oracle Ideas Page并且是已知的痛点(有趣的是并非所有人) - 请参阅Oracle Ideas Page 中的讨论

So the next step is to remove the aliases from the GROUP BY clause and the statement works ...所以下一步是从GROUP BY子句中删除别名,该语句有效......

select 
COL1 ||'-' || COL2 as x,
case when COL1 = 'A1' then COL2 ||'-' || COL1 else COL1 || '-' || COL2 end as y,
sum(COL3)
from tab
group by COL1 ||'-' || COL2,
case when COL1 = 'A1' then COL2 ||'-' || COL1 else COL1 || '-' || COL2 end;

... but is a classical example of an stinking code where every change must be made in identical way in two places. ...但这是一个臭代码的经典示例,其中每个更改都必须在两个地方以相同的方式进行。

Less know, but it works, is that you do not need to copy the exact expressions of the GROUP BY columns , list of all used original columns is enough .不太了解,但它的工作原理是您不需要复制GROUP BY列的确切表达式,所有使用的原始列的列表就足够了

Here an example - COL1, COL2 in GROUP BY covers all the expression used in the SELECT这里有一个例子COL1, COL2 GROUP BY COL1, COL2涵盖了SELECT使用的所有表达式

select 
COL1 ||'-' || COL2 as x,
case when COL1 = 'A1' then COL2 ||'-' || COL1 else COL1 || '-' || COL2 end as y,
sum(COL3)
from tab
group by COL1, COL2

X     Y      SUM(COL3)
----- ----- ----------
A1-B1 B1-A1          1 
A3-B3 A3-B3          3 
A2-B2 A2-B2          2 

My test data我的测试数据

create table tab as
select 'A1' col1, 'B1' col2, 1 col3 from dual union all
select 'A2' col1, 'B2' col2, 2 col3 from dual union all
select 'A3' col1, 'B3' col2, 3 col3 from dual;

Assuming that T4 is what is causing "duplication", you can solve this problem simply by using a correlated subquery:假设T4是导致“重复”的原因,您只需使用相关子查询即可解决此问题:

select . . .,
       (select sum(oit.mass)
        from ORDERITEMINVENTORY oii 
        where T1.ORDER_CODE = oii.ORDER_CODE AND T1.ORDER_ITEM = oii.ORDER_ITEM
       )
from . . .  -- leave `T4` out of this clause

No GROUP BY is then necessary.不需要GROUP BY This will probably also have better performance.这可能也会有更好的性能。

Note that this "seems" to work only for one aggregation column -- which solves your immediate problem.请注意,这“似乎”仅适用于一个聚合列——它解决了您的直接问题。 Oracle 12C supports lateral joins, which would allow multiple columns in a "correlated" subquery. Oracle 12C 支持横向连接,这将允许“相关”子查询中的多个列。

Also, I strongly recommend that you use meaningful table aliases.此外,我强烈建议您使用有意义的表别名。 In this code snippet, I replaced the meaningless T4 with oii , which are the first letters of each word in the table name.在此代码片段中,我将无意义的T4替换为oii ,即表名中每个单词的首字母。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM