AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 78805
Accepted
mruether
mruether
Asked: 2014-10-10 11:04:44 +0800 CST2014-10-10 11:04:44 +0800 CST 2014-10-10 11:04:44 +0800 CST

ORA-00937 ao calcular um subvalor em uma instrução de seleção agregada

  • 772

O problema descrito a seguir se aplica aos bancos de dados Oracle 11g. Também testei as instruções no MySQL e PostgreSQL sem problemas do tipo mencionado nesta pergunta.

Eu quero usar uma função de agregação em uma instrução de seleção que precisa de algum cálculo adicional para produzir o resultado. Meu objetivo principal é manter todo o cálculo em uma declaração, pois o resultado deve ser exibido literalmente no software de back-end.

Que haja uma tabela Tdefinida por este DDL

create table T(
  ID number,
  NUM number,
  TXT varchar(32)
);

insert into T (ID, NUM, TXT) values (1, 1, 'Text1');
insert into T (ID, NUM, TXT) values (2, 2, 'Text2');
insert into T (ID, NUM, TXT) values (3, 0, 'Text3');

Agora o objetivo é somar todos os valores do atributo num para todas as linhas selecionadas. Eu posso fazer isso usando

select sum(num) from T

Agora, para a parte complicada, suponha que haja uma segunda tabela a partir da qual calculamos um valor adicional a ser combinado com o resultado de nossa primeira seleção. O select envolvido retornará um único número por ser um valor agregado por si só. (Para manter o esquema simples desta demonstração, utilizo a mesma tabela, mas o problema descrito permanece independentemente da segunda tabela utilizada)

select case (select count(*) from T) when 0 then 1 else 0 end from dual;

Quando combinados, deixaremos de fora a select ... from dualparte que é usada apenas para obter o resultado intermediário exibido. Juntos, a consulta será

select (case (select count(t1.num) from T t1) when 0 then 1 else 0 end)*sum(t2.num) from T t2;

onde atribuímos aliases a cada tabela para tornar o uso claro.

O resultado dessa consulta é uma exceção do Oracle: ORA-00937: not a single-group group function. Como a expressão case produz um único valor e nenhuma referência é feita a nenhum recurso fora da expressão, eu me pergunto qual princípio básico eu violei com essa instrução select. Além disso, MySQL e PostgreSQL produzem o resultado desejado.

Enquanto procurava uma solução, também tentei esta instrução select:

select (case when (exists (select 1 from T where NUM = 0)) then 0 else 1 end)*sum(NUM) as p from T where NUM > 0;

Aqui descartei a função de agregação interna count(t1.num)para descartar problemas com agregações aninhadas. Esta instrução deu a mesma mensagem de erro do Oracle, enquanto o cálculo do valor adicional não causou problemas:

select (case when (exists (select 1 from T where NUM = 0)) then 0 else 1 end) as p from dual;

Pergunta : Alguém pode explicar o que está errado? (E principalmente me pergunto se o Oracle não implementa o padrão SQL, ou se o MySQL e o PostgreSQL estendem o padrão).

Tecnicamente, a solução para o meu problema seria uma junção em que ambos, o agregado e o valor adicional são calculados separadamente e, em seguida, combinados na instrução de seleção externa. Meu foco não está em como alguém pode resolver esse problema, mas em estou perdendo alguma coisa no Oracle ou está faltando algo no Oracle? .

mysql postgresql
  • 1 1 respostas
  • 556 Views

1 respostas

  • Voted
  1. Best Answer
    Sentinel
    2015-07-09T11:41:11+08:002015-07-09T11:41:11+08:00

    Seu valor adicional calculado:

    (select count(t1.num) from T t1)
    

    É uma subconsulta escalar, que é uma expressão dinâmica em vez de estática. Como tal, é tratado da mesma forma que uma coluna no que diz respeito ao agregado e precisa ser incluído na cláusula group by para evitar o ORA-00937: not a single-group group functionerro

    No entanto, o oracle não permite subconsultas como parte da cláusula group by e tentando incluir a subconsulta escalar e/ou toda a instrução case:

    group by (case (select count(*) cnt from t t1) when 0 then 1 else 0 end)
    

    apenas resulta em um ORA-22818: subquery expressions not allowed hereerro.

    As únicas maneiras de contornar isso são converter sua subconsulta escalar em um valor agregado da seguinte forma:

    max(case (select count(*) cnt from t t1) when 0 then 1 else 0 end)
    

    ou

    (case max((select count(*) cnt from t t1)) when 0 then 1 else 0 end)
    

    ou reescreva sua consulta para mover a subconsulta escalar não agregada para fora da consulta agregada:

    select (case (select count(*) cnt from t t1) when 0 then 1 else 0 end) * sum
      from (select sum(t3.num) sum from t t3) t2;
    

    ou pré-compute sua subconsulta escalar para que ela possa ser usada na cláusula group by:

    select case t1.cnt when 0 then 1 else 0 end * sum(t2.num)
      from t t2
         , (select count(*) cnt from t) t1
     group by case t1.cnt when 0 then 1 else 0 end
    
    • 2

relate perguntas

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve