我有以下Oracle SQL查询的示例,该查询失败,并显示"ORA-00979:Not a group by Expression".如果删除"SELECT COUNT(*)FROM(...)"包装,查询将按预期工作.其 idea 是获取内部查询返回的行数.

我想知道为什么它不能和这个包装纸一起工作.有人能解释一下为什么会发生这种情况吗?我只是对它发生的原因感兴趣.

预期的结果是,该查询将返回内部查询返回的所有行的计数.

几天来,我一直在寻找原因和解决方案,但没有运气.我在互联网上也找不到关于这方面的信息.

当我处理它时,我注意到以下更改使查询可以工作:

  1. 删除连接(删除此部分-"NVL(D.Computer_Price,9999)||NVL(t3.achory_Price,9999)").
  2. go 掉拥有.
  3. 将"JSON_VALUE(Laptop_INFO,‘$.Model’)INFO"更改为"NULL INFO".
  4. go 掉联盟的一部分.

如有任何建议或意见,将不胜感激.

备注:

  1. Oracle SQL的版本为19c.
  2. 这只是从原始查询准备的查询的一个假示例.但这也证明了这一问题.因此,如果查询或查询 struct 的结果对您没有意义,请不要介意.
  3. 原始查询是自动生成的,并且更复杂,因此我不太可能对此查询的 struct 进行太多更改.我只是希望为它失败的原因找到一个解释.

以下是查询:

-- QUERY
select count(*) from (
    SELECT
      CASE WHEN GROUPING_ID(t3.accessory_name, D.name, NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999)) != 0 THEN COUNT(*) END "Records",
      t3.accessory_name "accessory name",
      D.name "device name",
      SUM(D.computer_price) "computer price",
      SUM(D.laptop_price) "laptop price",
      SUM(t3.accessory_price) "accessory price",
      CASE WHEN GROUPING_ID(t3.accessory_name, D.name, NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999)) = 0 THEN ANY_VALUE(t3.accessory_info) END "accessory info"
    FROM (
      SELECT
        computer_id id,
        computer_name name,
        computer_info info,
        computer_price computer_price,
        null laptop_price
      FROM computer
      UNION ALL
      SELECT
        laptop_id id,
        laptop_name name,
        JSON_VALUE(laptop_info, '$.model') info,
        null computer_price,
        laptop_price laptop_price
      FROM laptop
    ) D
    JOIN accessory t3 on t3.accessory_id = D.id  
    GROUP BY
      ROLLUP (t3.accessory_name, D.name, NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999))
    HAVING
      (GROUPING_ID(t3.accessory_name, D.name, NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999))=3)
    ORDER BY NVL(t3.accessory_name, 0), NVL(D.name, 0), NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999) DESC
);

以下是用于准备测试表和测试数据的脚本:

-- CREATE TEST TABLES
create table computer(computer_id NUMBER, computer_name varchar2(50), computer_info varchar2(50), computer_price NUMBER);
create table laptop(laptop_id NUMBER, laptop_name varchar2(50), laptop_info varchar2(50), laptop_price NUMBER);
create table accessory(accessory_id NUMBER, accessory_name varchar2(50), accessory_info varchar2(50), accessory_price NUMBER);

-- INSERT TEST DATA
insert into computer (computer_id, computer_name, computer_info, computer_price) values (1, 'computer 1', 'some info about computer 1', 10);
insert into computer (computer_id, computer_name, computer_info, computer_price) values (2, 'computer 2', 'some info about computer 2', 20);
insert into computer (computer_id, computer_name, computer_info, computer_price) values (3, 'computer 3', 'some info about computer 3', 30);

insert into laptop (laptop_id, laptop_name, laptop_info, laptop_price) values (1, 'laptop 1', '{''model'': ''model 1''}', 15);
insert into laptop (laptop_id, laptop_name, laptop_info, laptop_price) values (2, 'laptop 2', '{''model'': ''model 2''}', 25);
insert into laptop (laptop_id, laptop_name, laptop_info, laptop_price) values (3, 'laptop 3', '{''model'': ''model 3''}', 35);

insert into accessory (accessory_id, accessory_name, accessory_info, accessory_price) values (1, 'accessory 1', 'accessory 1 info', 1);
insert into accessory (accessory_id, accessory_name, accessory_info, accessory_price) values (2, 'accessory 2', 'accessory 2 info', 2);
insert into accessory (accessory_id, accessory_name, accessory_info, accessory_price) values (3, 'accessory 3', 'accessory 3 info', 3);

我花了几天时间寻找解决方案,但在网上找不到任何类似的问题.此外,我还try 用不同的方式重写包装器,但结果是一样的.

推荐答案

我能够解决这个问题.这与甲骨文优化器有关.当我们运行查询时,Oracle Optimizer会try 优化查询以使其更快、更高效地工作.在优化过程中,Oracle执行一些查询转换.在这种情况下,Oracle做错了,查询失败.

要解决此问题,我们需要禁用查询转换,方法是指定Oracle Optimizer不转换原始查询并按原样执行它. 要做到这一点,我们可以使用优化器提示NO_QUERY_TRANSION.

添加此提示后,查询按预期工作.下面是一个例子:

-- QUERY
select count(*) from (
    SELECT
      /*+ NO_QUERY_TRANSFORMATION */
      CASE WHEN GROUPING_ID(t3.accessory_name, D.name, NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999)) != 0 THEN COUNT(*) END "Records",
      t3.accessory_name "accessory name",
      D.name "device name",
      SUM(D.computer_price) "computer price",
      SUM(D.laptop_price) "laptop price",
      SUM(t3.accessory_price) "accessory price",
      CASE WHEN GROUPING_ID(t3.accessory_name, D.name, NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999)) = 0 THEN ANY_VALUE(t3.accessory_info) END "accessory info"
    FROM (
      SELECT
        computer_id id,
        computer_name name,
        computer_info info,
        computer_price computer_price,
        null laptop_price
      FROM computer
      UNION ALL
      SELECT
        laptop_id id,
        laptop_name name,
        JSON_VALUE(laptop_info, '$.model') info,
        null computer_price,
        laptop_price laptop_price
      FROM laptop
    ) D
    JOIN accessory t3 on t3.accessory_id = D.id  
    GROUP BY
      ROLLUP (t3.accessory_name, D.name, NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999))
    HAVING
      (GROUPING_ID(t3.accessory_name, D.name, NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999))=3)
    ORDER BY NVL(t3.accessory_name, 0), NVL(D.name, 0), NVL(D.computer_price, 9999) || NVL(t3.accessory_price, 9999) DESC
);

希望这对其他人有帮助,因为它让我花了一个多星期的时间来解决这个问题.

Sql相关问答推荐

当有空单元格时,如何连接列

BigQuery`喜欢ANY‘和`不喜欢ANY’

如何在SQL Server中拆分包含字符和数字的列?

如何在SQL Server中统计按备注分组的记录数

从包含PostgreSQL中的JSON值的列中提取列表或目录

如何用客户名称计算sum(dr)和sum(cr)

如何用QuestDB生成蜡烛图?

如何在多列上编写具有不同条件的查询?

在 Postgres 中将结果按几十年划分

POSTGRES to_timestamp() 假定 UTC 字符串为本地时间

通过ID和数据找到每个不同的值

如何计算两个非周期性时间序列+分组的重叠持续时间

在Snowflake中如何使用SQL对版本字符串进行排序?

根据行号将列转置为没有任何id或键列的行

在 postgresql 中保存带有时间戳的几何类型数据

我如何编写一个遍历数组数组并将所有值连接成一个字符串的 postgres 函数

计算 PostgreSQL 中的平均会话长度

查找具有相同连接列数据的所有记录

为每组填写行以进行旋转

在 MindsDB SQL 编辑器中运行 PostgreSQL 条目 ID 时出现未知 Select 目标错误