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 / 15019
Accepted
Leigh Riffel
Leigh Riffel
Asked: 2012-03-15 10:41:57 +0800 CST2012-03-15 10:41:57 +0800 CST 2012-03-15 10:41:57 +0800 CST

Produto de n Linhas

  • 772

A partir desses dados (supondo que o número de linhas não seja conhecido antecipadamente):

with q1 as (select mod(ora_hash(level),5) c1 from dual connect by level <=4)
select * from q1;
/*
C1
--
 2 
 1 
 4 
 1
*/

Eu quero o produto da coluna c1 de todas as linhas. Algo como os resultados de SUM(c1) apenas, quero cada valor multiplicado pelos outros, em vez de adicionados. Nesse caso, seria 2 * 1 * 4 * 1 = 8.

/*
X1
--
 8
*/

Os dados podem conter números negativos e zero, que podem ser simulados usando:

with q1 as (select mod(ora_hash(level),5)-1 c1 from dual connect by level <=4)
select * from q1;

ou

with q1 as (select mod(ora_hash(level),5)-3 c1 from dual connect by level <=4)
select * from q1;

Sei que isso pode ser feito com função de agregação personalizada, mas estou interessado em abordagens nativas.

oracle oracle-11g-r2
  • 2 2 respostas
  • 315 Views

2 respostas

  • Voted
  1. Best Answer
    Justin Cave
    2012-03-15T10:46:10+08:002012-03-15T10:46:10+08:00

    Para produtos agregados suficientemente pequenos, você pode usar o velho truque de somar os logaritmos e exponenciar o resultado

    SQL> ed
    Wrote file afiedt.buf
    
      1  with q1
      2    as (select mod(ora_hash(level),5) c1
      3          from dual
      4       connect by level <=4)
      5  select exp(sum(ln(c1)))
      6*   from q1
    SQL> /
    
    EXP(SUM(LN(C1)))
    ----------------
                   8
    

    Como você está usando 11.2, é um pouco mais detalhado (embora alguém possa descobrir uma versão mais simples), mas você também pode usar expressões de tabela comuns recursivas

    SQL> ed
    Wrote file afiedt.buf
    
      1  with
      2  q1 as (select level l, mod(ora_hash(level),5) c1
      3           from dual
      4        connect by level <= 4),
      5  num(n, c1, running_product)
      6  as
      7  (
      8    select 1 as N,
      9           null as c1,
     10           1 as running_product
     11      from dual
     12    union all
     13    select N+1,
     14           q1.c1,
     15           (q1.c1)*running_product
     16      from num
     17           join q1 on (num.N = q1.l)
     18  )
     19  select running_product
     20    from (select num.*,
     21                 rank() over (order by N desc) rnk
     22            from num)
     23*  where rnk = 1
    SQL> /
    
    RUNNING_PRODUCT
    ---------------
                  8
    
    • 5
  2. Leigh Riffel
    2012-03-15T13:04:01+08:002012-03-15T13:04:01+08:00

    Justin me inspirou a tentar uma versão usando a MODELcláusula. Este é meu primeiro uso da cláusula, então estou aberto a qualquer crítica construtiva. Criei três CTEs para testar números negativos e zero.

    with q1 as (select level N, mod(ora_hash(level),5) c1 from dual connect by level <=4),
         q2 as (select N, c1-1 c1 from q1),
         q3 as (select N, c1-3 c1 from q1)
    select c1 from q1
    model return updated rows dimension by (N) measures (c1) 
    rules iterate (999) until (c1[iteration_number+1] IS NULL) (
       c1[1] = c1[1] * NVL(c1[iteration_number+2],1)
    )
    union all
    select c1 from q2
    model return updated rows dimension by (N) measures (c1) 
    rules iterate (999) until (c1[iteration_number+1] IS NULL) (
       c1[1] = c1[1] * NVL(c1[iteration_number+2],1)
    )
    union all
    select c1 from q3
    model return updated rows dimension by (N) measures (c1) 
    rules iterate (999) until (c1[iteration_number+1] IS NULL) (
       c1[1] = c1[1] * NVL(c1[iteration_number+2],1)
    );
    

    Aqui está uma versão detalhada da solução de log que lida com valores negativos e zero.

    with q1 as (select mod(ora_hash(level),5)  c1 from dual connect by level <=4),
         q2 as (select c1-1 c1 from q1),
         q3 as (select c1-3 c1 from q1)
    select 'q1',  case when sum(case when c1 < 0 then -1 
       when c1 > 0 then 1 else 0 end) >= 0 then 1 else -1 end *
       decode(min(abs(c1)),0,0,Round(exp(sum(ln(abs(nullif(c1,0))))))) x1  
       from q1
    union all   
    select 'q2', case when sum(case when c1 < 0 then -1 
       when c1 > 0 then 1 else 0 end) >= 0 then 1 else -1 end *
       decode(min(abs(c1)),0,0,Round(exp(sum(ln(abs(nullif(c1,0))))))) x1  
       from q2
    union all   
    select 'q3', case when sum(case when c1 < 0 then -1 
       when c1 > 0 then 1 else 0 end) >= 0 then 1 else -1 end *
       decode(min(abs(c1)),0,0,Round(exp(sum(ln(abs(nullif(c1,0))))))) x1  
       from q3
    ; 
    

    Finalmente, aqui está um CTE recursivo semelhante ao Justins, mas um pouco mais simples.

    with q1 as (select level N, mod(ora_hash(level),5) c1 from dual connect by level <=4),
         q2 as (select N, c1-1 c1 from q1),
         q3 as (select N, c1-3 c1 from q1),
         x1 (N, Product) as (
            select 1 N, 1 Product from dual
            union all
            select x1.N+1 N, q1.c1 * x1.Product Product from x1 
            join q1 on (x1.N = q1.N)
            ),
         x2 (N, Product) as (
            select 1 N, 1 Product from dual
            union all
            select x2.N+1 N, q2.c1 * x2.Product Product from x2
            join q2 on (x2.N = q2.N)
            ),
         x3 (N, Product) as (
            select 1 N, 1 Product from dual
            union all
            select x3.N+1 N, q3.c1 * x3.Product Product from x3
            join q3 on (x3.N = q3.N)
            )
    select Product from (select N, Product, max(N) OVER () MaxN from x1) where N = MaxN
    union all
    select Product from (select N, Product, max(N) OVER () MaxN from x2) where N = MaxN
    union all
    select Product from (select N, Product, max(N) OVER () MaxN from x3) where N = MaxN;
    
    • 2

relate perguntas

  • Backups de banco de dados no Oracle - Exportar o banco de dados ou usar outras ferramentas?

  • ORDER BY usando prioridades personalizadas para colunas de texto

  • Interface sqlplus confortável? [fechado]

  • Como encontrar as instruções SQL mais recentes no banco de dados?

  • Como posso consultar nomes usando expressões regulares?

Sidebar

Stats

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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