Eduardo e colegas, Eduardo: Grato pela dica do ASCII. aprendi mais uma.
Desculpem-me pelo e-mail extenso, mas segue aqui o relato em detalhes do problema que estou enfrentando. A solução deve ser simples, apesar do e-mail extenso. Observações: a.) tentei fazer o ORDER BY sem usar o DENSE_RANK e o resultado é o mesmo, não funcionou na query original postada abaixo. Estranho que na simulação funcionou. b.) Parece que o ORDER BY (desc , asc) não está sendo usado corretamente, por isso estou postando o problema, que certamente será lessons learn para o grupo. c.) Versão do oracle : Oracle 10g. Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod PL/SQL Release 10.2.0.4.0 - Production CORE 10.2.0.4.0 Production TNS for 32-bit Windows: Version 10.2.0.4.0 - Production NLSRTL Version 10.2.0.4.0 - Production d.) gostaria de resolver isso somente com SQL, sem ter que fazer código em PL/SQL. Objetivo: Obter uma lista de valores com classificação pelo maior valor. Regra do Negócio: O maior VALOR_1 será o campeão e o DENSE_RANK dele deve ser 1. Se empatar no VALOR_1, analisar o maior VALOR_2. Se ainda assim empatar, o critério de desempate é o menor CODE. 1.) Query montada para simular usando o DENSE_RANK. (AQUI FUNCIONOU) select id, periodo, valor_1, valor_2, codigo, DENSE_RANK() OVER (PARTITION BY periodo ORDER BY valor_1 desc , valor_2 desc , codigo asc) AS DENSE_RANK from (select id, periodo, sum(num1) valor_1, sum(num2) valor_2, codigo from(select 1 id, 1 periodo, 100.34 as num1, 200.454545 as num2, '0691' as codigo from dual union all select 2 id, 1 periodo, 100.34 as num1, 200.454545 as num2, '0447' as codigo from dual union all select 3 id, 1 periodo, 30 as num1, 1200 as num2, '0999' as codigo from dual union all select 4 id, 1 periodo, 30 as num1, 1200 as num2, '0001' as codigo from dual union all select 5 id, 1 periodo, 33 as num1, 1200 as num2, '0999' as codigo from dual union all select 6 id, 1 periodo, 30 as num1, 1200 as num2, '0888' as codigo from dual) group by id, periodo, codigo) Resultado: id per. valor_1 valor_2 code dense_rank ---- ----- --------------------------- -------------------------- -------- ----------------- 2 1 100,34 200,454545 0447 1 1 1 100,34 200,454545 0691 2 5 1 33 1200 0999 3 4 1 30 1200 0001 4 6 1 30 1200 0888 5 3 1 30 1200 0999 6 Conclusão: O valor 100,34 empatou nas 2 primeiras linhas, O valor 200,454545 empatou nas 2 primeiras linhas Preciso que o menor código desempate o ranking. No caso simulado fez corretamente, pois o 0447 é o menor código das linhas empatadas e veio com DENSE_RANK = 1. 2.) Query original (AQUI NÃO FUNCIONA). Datatypes relevantes: A coluna attribute_value é um NUMBER(38,8) e a coluna CODE é um VARCHAR2(4). A query abaixo, fiz tambem, sem SUM, trazendo os valores direto em 1 linha só, colocando duas vezes a tabela entidade_summary e o problema persiste. SELECT id, periodo, valor_1, valor_2, code, DENSE_RANK() OVER (PARTITION BY periodo ORDER BY valor_1 desc, valor_2 desc, code asc) AS DENSE_RANK FROM (SELECT parent_id id, si_period_id periodo, sum(valor_1) valor_1, sum(valor_2) valor_2, code FROM(SELECT d.parent_id, d.si_period_id, d.attribute_value valor_1, null valor_2, entidade.code FROM entidade_summary d , entidade WHERE d.attribute_code = 'VALOR_1' AND d.si_period_id = 1 AND d.attribute_value IS NOT NULL AND d.reference_year IS NULL AND d.parent_id = entidade.id UNION ALL SELECT d.parent_id, d.si_period_id, null valor_1, d.attribute_value valor_2, entidade.code FROM entidade_summary d , entidade WHERE d.attribute_code = 'VALOR_2' AND d.si_period_id = 1 AND d.attribute_value IS NOT NULL AND d.reference_year IS NULL AND d.parent_id = entidade.id ) GROUP BY parent_id, si_period_id, code ) Resultado gerado pela query original : id per. valor_1 valor_2 code dense_rank ---- ----- --------------------------- -------------------------- -------- ----------------- 7 1 16262927843,1253 1303006,45802409 0688 1 18 1 16262927843,1153 1303006,45802409 0691 2 15 1 16262927843,1153 1303006,45802409 0447 3 1 1 16262927843,1153 1303006,45802409 0687 4 19 1 3930077927,06403 314894,446515 0348 5 Análise: O valor 16262927843,1253 é o campeão, está com DENSE_RANK = 1. Isto está correto. O valor 16262927843,1153 aparece na segunda e terceira linha. Então empatou. O segundo critério é avaliar VALOR_2. que também empatou na primeira e segunda linha. O critério final de desempate é classificar pelo menor CODE. Como o código 0447 é menor, é esperado que ele apareça no DENSE_RANK = 2 e não 3. O que parece não estar funcionando é essa parte da query: ORDER BY valor_1 desc, valor_2 desc, code asc) AS DENSE_RANK Parece que não está fazendo a ordenação ascendente pela coluna CODE. Pois, empatou em VALOR_1, empatou em VALOR_2 e o desempate seria pelo menor código, no entanto isso não está acontecendo, pois o CODE 0447 veio como 3 e não como 2. Resultado pretendido: id per. valor_1 valor_2 code dense_rank ---- ----- --------------------------- -------------------------- -------- ----------------- 3 15 1 16262927843,1153 1303006,45802409 0447 2 2 18 1 16262927843,1153 1303006,45802409 0691 3 Se alguém souber o motivo pelo qual o DESC, DESC, ASC não acontece, ficarei grato. Grato Eriovaldo 2009/4/23 Claro, Eduardo <eduardo.cl...@eds.com> > > > Gleyson, > > A função ASCII retorna o código ASCII do primeiro caractere da sua string. > Portanto, ASCII('0691') e ASCII('0447') na verdade serão executados como > simplesmente ASCII('0'), e por isso o resultado é igual. > > Quanto à sua query, por favor poste um exemplo completo, que possa ser > executado e verificado, para facilitar. > > Seu exemplo pode por exemplo ser do tipo que você usou no início da sua > explicação, com dois SELECTs FROM DUAL, mas já usando o DENSE RANK e > reproduzindo o problema, ok? > > -- > > Eduardo Claro > > From: oracle_br@yahoogrupos.com.br <oracle_br%40yahoogrupos.com.br>[mailto: > oracle_br@yahoogrupos.com.br <oracle_br%40yahoogrupos.com.br>] On Behalf > Of Eriovaldo Andrietta > Sent: quinta-feira, 23 de abril de 2009 11:27 > To: oracle_br@yahoogrupos.com.br <oracle_br%40yahoogrupos.com.br> > Subject: Re: [oracle_br] Dúvida sobre Order by > > > Gleyson, > > 1.) Eu já tenho um outro order by, que é usado depois que consigo o > DENSE_RANK. > O meu problema é o order by que gera o DENSE_RANK, pois espero que a coluna > alfanumérica seja classificada de forma ascendente para trazer o código > 0447 com DENSE_RANK = 1 e não igual a 2. Estou entendendo que o DENSE_RANK > é > o rownum do resultado. > > 2.) Estou tentando fazer um order by direto na query sem DENSE_RANK e > também não está funcionando. > > ORDER BY d.si_period_id asc, -- 01 > d.attribute_value desc, -- 02 > e.attribute_value desc, -- 03 > entidade.code asc -- 04 > 1 2 3 4 > dense > 1 16262927843,11529920 1303006,45802409 0691 1 18 > 1 16262927843,11529920 1303006,45802409 0447 2 15 > 1 3930077927,06403017 314894,44651500 0348 3 19 > 1 3744493176,06001997 300054,66430277 0450 4 13 > > Preciso que o dense da segunda linha seja 1 e o dense da primeira seja 2 > que é a classificação ascendente da quarta coluna, o código menor primeiro. > > 3.) Curioso: > > se eu fizer : > > SQL> select ascii('0691') from dual; > > ASCII('0691') > ------------- > 48 > SQL> select ascii('0447') from dual; > > ASCII('0447') > ------------- > 48 > > Será que o order by está usando isso para classificar ? > > Grato pela ajuda. > > 2009/4/23 Gleyson Melo <gleysonm...@gmail.com > <gleysonmelo%40gmail.com><mailto: > gleysonmelo%40gmail.com <gleysonmelo%2540gmail.com>> > > > > > > > > Fala Eriovaldo! > > Cara, aquele ORDER BY foi apenas pra gerar o valor final do RANK. Pra > gerar > > a saída que tu queres, tens que colocar o ORDER BY no final da consulta > > também. > > > > 2009/4/22 Eriovaldo Andrietta > > <ecandrie...@gmail.com<ecandrietta%40gmail.com><mailto: > ecandrietta%40gmail.com <ecandrietta%2540gmail.com>> <ecandrietta% > 40gmail.com>> > > > > > > > > > > > > > > > > Olá pessoal, > > > > > > Veja se alguém pode me ajudar: > > > > > > Quando faço esta query ordenando a coluna text de forma desc tenho 0447 > > no > > > final: > > > select 100 as num1, 200 as num2, > > > '0691' as text from dual > > > union all > > > select 100 as num1, 200 as num2, > > > '0447' as text from dual > > > order by 1 desc, 2 desc, 3 desc > > > > > > 1 100 200 0691 > > > 2 100 200 0447 > > > > > > Quando faço esta query ordenando a coluna text de forma asc tenho 0447 > no > > > começo: > > > > > > select 100 as num1, 200 as num2, > > > '0691' as text from dual > > > union all > > > select 100 as num1, 200 as num2, > > > '0447' as text from dual > > > order by 1 desc, 2 desc, 3 asc > > > > > > 1 100 200 0447 > > > 2 100 200 0691 > > > > > > até ai tudo bem. é isso mesmo que eu quero, O desc desc asc funciona, > > > porém: > > > > > > quando uso esse mesmo recurso em: > > > > > > DENSE_RANK() > > > OVER (PARTITION BY d.si_period_id > > > ORDER BY d.attribute_value desc , > > > e.attribute_value desc , > > > f.code asc) AS DENSE_RANK > > > > > > o 0447 sai sempre no final. > > > > > > Eu preciso do 0447 na primeira linha e a instrução não faz isso. > > > > > > Sai assim: > > > > > > 1 18 1 16262927843,11529920 1303006,45802409 0691 1 > > > 2 15 1 16262927843,11529920 1303006,45802409 0447 2 > > > > > > E preciso do resultado assim, o menor código antes: > > > > > > 1 18 1 16262927843,11529920 1303006,45802409 0447 1 > > > 2 15 1 16262927843,11529920 1303006,45802409 0691 2 > > > > > > O que tem de errado nisso ? > > > > > > Grato > > > Eriovaldo > > > > > > [As partes desta mensagem que não continham texto foram removidas] > > > > > > > > > > > > > -- > > Atenciosamente, > > Gleyson Melo > > Oracle Database 10g Administrator Certified Professional > > > > [As partes desta mensagem que não continham texto foram removidas] > > > > > > > > [As partes desta mensagem que não continham texto foram removidas] > > [As partes desta mensagem que não continham texto foram removidas] > > > [As partes desta mensagem que não continham texto foram removidas]