Diferentes ORDER em UNION

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
thiago_r_f
Rank: Programador Pleno
Rank: Programador Pleno
Mensagens: 43
Registrado em: Qui, 17 Abr 2008 4:02 pm
Localização: Rio de Janeiro - RJ
O Backup é meu pastor e nada me faltará!
Thiago Rodrigues de Farias

Olá a todos.
Gostaria de saber se existe alguma maneira de trazer ordens diferentes dentro de uma união de selects. Dentro do SQL abaixo está o ponto onde, teoricamente, interessa: determinar uma ordem num conjunto de dados unidos a outro com uma ordenação distinta ou sem ordenação.
Este SQL é designado para um cursor e, portanto, evitaria a criação de uma tabela temporária. está tudo direitinho, só falta esse problema de ORDER.

Selecionar tudo

      SELECT A.CODPAI CODPAI, B.NO_PAIS DESCRICAO,
             SUM(A.FOBATU) ACUM_FOB_ANO_ATU, 
             SUM(A.FOBATU) * 100 /*/ TOT_ACUM_FOB_ANO_ATU ACUM_PART_ANO_ATU*/,             
             SUM(A.FOBANT) ACUM_FOB_ANO_ANT, 
             SUM(A.FOBANT) * 100 /*/ TOT_ACUM_FOB_ANO_ANT ACUM_PART_ANO_ANT*/, 
             REPLACE( TO_CHAR( DECODE(SUM(A.FOBANT),0,0,
                    (SUM(A.FOBATU) - SUM(A.FOBANT)) / SUM(A.FOBANT) * 100)  ,'999D99'), '#######', NULL) ACUM_VAR, 
             (SUM(A.FOBATU) - SUM(A.FOBMAT)) mês_FOB_ANO_ATU, 
             (SUM(A.FOBATU) - SUM(A.FOBMAT)) * 100 /*/ TOT_mês_FOB_ANO_ATU mês_PART_ANO_ATU*/, 
             (SUM(A.FOBANT) - SUM(A.FOBMAN)) mês_FOB_ANO_ANT, 
             (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100 /*/ TOT_mês_FOB_ANO_ANT mês_PART_ANO_ANT*/,     
             REPLACE( TO_CHAR( DECODE((SUM(A.FOBANT) - SUM(A.FOBMAN)),0,0,
                   ((SUM(A.FOBATU) - SUM(A.FOBMAT)) - (SUM(A.FOBANT) - SUM(A.FOBMAN))) / 
                    (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100) ,'999D99'), '#######', NULL) mês_VAR
       FROM BD.BCEPAP A, BD.T200_PAIS B
      WHERE A.CODPAI = B.CO_PAIS
        AND A.CODPAI <> '990'
      GROUP BY A.CODPAI, B.NO_PAIS
-- AQUI ESTÁ O PROBLEMA!!! *******************************************************
      ORDER BY 3 DESC
-- *******************************************************************************
      UNION
            SELECT A.CODPAI CODPAI, B.NO_PAIS DESCRICAO,
             SUM(A.FOBATU) ACUM_FOB_ANO_ATU, 
             SUM(A.FOBATU) * 100 /*/ TOT_ACUM_FOB_ANO_ATU ACUM_PART_ANO_ATU*/,             
             SUM(A.FOBANT) ACUM_FOB_ANO_ANT, 
             SUM(A.FOBANT) * 100 /*/ TOT_ACUM_FOB_ANO_ANT ACUM_PART_ANO_ANT*/, 
             REPLACE( TO_CHAR( DECODE(SUM(A.FOBANT),0,0,
                    (SUM(A.FOBATU) - SUM(A.FOBANT)) / SUM(A.FOBANT) * 100)  ,'999D99'), '#######', NULL) ACUM_VAR, 
             (SUM(A.FOBATU) - SUM(A.FOBMAT)) mês_FOB_ANO_ATU, 
             (SUM(A.FOBATU) - SUM(A.FOBMAT)) * 100 /*/ TOT_mês_FOB_ANO_ATU mês_PART_ANO_ATU*/, 
             (SUM(A.FOBANT) - SUM(A.FOBMAN)) mês_FOB_ANO_ANT, 
             (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100 /*/ TOT_mês_FOB_ANO_ANT mês_PART_ANO_ANT*/,     
             REPLACE( TO_CHAR( DECODE((SUM(A.FOBANT) - SUM(A.FOBMAN)),0,0,
                   ((SUM(A.FOBATU) - SUM(A.FOBMAT)) - (SUM(A.FOBANT) - SUM(A.FOBMAN))) / 
                    (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100) ,'999D99'), '#######', NULL) mês_VAR
       FROM BD.BCEPAP A, BD.T200_PAIS B
      WHERE A.CODPAI = B.CO_PAIS
        AND A.CODPAI = '990'
      GROUP BY A.CODPAI, B.NO_PAIS
      /*ORDER BY 3 DESC*/;
Valeu!
Abs.
ricardorauber
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 96
Registrado em: Qua, 21 Jun 2006 11:33 pm
Localização: Canoas RS

Se eu entendi bem, você quer que o resultado venha todos os registros do primeiro sql ordenados internamente e logo abaixo venha os registros do segundo sql ordenados internamente também, ao invés de fazer uma ordenação para todos os registros, estou correto?
thiago_r_f
Rank: Programador Pleno
Rank: Programador Pleno
Mensagens: 43
Registrado em: Qui, 17 Abr 2008 4:02 pm
Localização: Rio de Janeiro - RJ
O Backup é meu pastor e nada me faltará!
Thiago Rodrigues de Farias

É isso mesmo Ricardo!!!
Já andei pesquisando e não tem como fazer um ORDER BY do jeito que eu coloquei no código.
Tentei fazer uma consulta unindo da seguinte maneira:

Selecionar tudo

      SELECT  * 
        FROM  (SELECT A.CODPAI CODPAI, B.NO_PAIS DESCRICAO,
                       SUM(A.FOBATU) ACUM_FOB_ANO_ATU, 
                       SUM(A.FOBATU) * 100 /*/ TOT_ACUM_FOB_ANO_ATU ACUM_PART_ANO_ATU*/,
                       SUM(A.FOBANT) ACUM_FOB_ANO_ANT, 
                       SUM(A.FOBANT) * 100 /*/ TOT_ACUM_FOB_ANO_ANT ACUM_PART_ANO_ANT*/, 
                       REPLACE( TO_CHAR( DECODE(SUM(A.FOBANT),0,0,
                              (SUM(A.FOBATU) - SUM(A.FOBANT)) / SUM(A.FOBANT) * 100)  ,'999D99'), '#######', NULL) ACUM_VAR, 
                       (SUM(A.FOBATU) - SUM(A.FOBMAT)) mês_FOB_ANO_ATU, 
                       (SUM(A.FOBATU) - SUM(A.FOBMAT)) * 100 /*/ TOT_mês_FOB_ANO_ATU mês_PART_ANO_ATU*/, 
                       (SUM(A.FOBANT) - SUM(A.FOBMAN)) mês_FOB_ANO_ANT, 
                       (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100 /*/ TOT_mês_FOB_ANO_ANT mês_PART_ANO_ANT*/, 
                       REPLACE( TO_CHAR( DECODE((SUM(A.FOBANT) - SUM(A.FOBMAN)),0,0,
                             ((SUM(A.FOBATU) - SUM(A.FOBMAT)) - (SUM(A.FOBANT) - SUM(A.FOBMAN))) / 
                              (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100) ,'999D99'), '#######', NULL) mês_VAR
                 FROM BD.BCEPAP A, BD.T200_PAIS B
                WHERE A.CODPAI = B.CO_PAIS
                  AND A.CODPAI <> '990' 
                GROUP BY A.CODPAI, B.NO_PAIS
                ORDER BY 3 DESC)
      UNION
      SELECT A.CODPAI CODPAI, B.NO_PAIS DESCRICAO,
               SUM(A.FOBATU) ACUM_FOB_ANO_ATU, 
               SUM(A.FOBATU) * 100 /*/ TOT_ACUM_FOB_ANO_ATU ACUM_PART_ANO_ATU*/,
               SUM(A.FOBANT) ACUM_FOB_ANO_ANT, 
               SUM(A.FOBANT) * 100 /*/ TOT_ACUM_FOB_ANO_ANT ACUM_PART_ANO_ANT*/, 
               REPLACE( TO_CHAR( DECODE(SUM(A.FOBANT),0,0,
                      (SUM(A.FOBATU) - SUM(A.FOBANT)) / SUM(A.FOBANT) * 100)  ,'999D99'), '#######', NULL) ACUM_VAR, 
               (SUM(A.FOBATU) - SUM(A.FOBMAT)) mês_FOB_ANO_ATU, 
               (SUM(A.FOBATU) - SUM(A.FOBMAT)) * 100 /*/ TOT_mês_FOB_ANO_ATU mês_PART_ANO_ATU*/, 
               (SUM(A.FOBANT) - SUM(A.FOBMAN)) mês_FOB_ANO_ANT, 
               (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100 /*/ TOT_mês_FOB_ANO_ANT mês_PART_ANO_ANT*/, 
               REPLACE( TO_CHAR( DECODE((SUM(A.FOBANT) - SUM(A.FOBMAN)),0,0,
                     ((SUM(A.FOBATU) - SUM(A.FOBMAT)) - (SUM(A.FOBANT) - SUM(A.FOBMAN))) / 
                      (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100) ,'999D99'), '#######', NULL) mês_VAR
        FROM BD.BCEPAP A, BD.T200_PAIS B
       WHERE A.CODPAI = B.CO_PAIS
         AND A.CODPAI = '990' 
       GROUP BY A.CODPAI, B.NO_PAIS
Esta foi a última tentativa pra ver se forçava uma saída dentro do que eu queria, mas o resultado exibe uma ordenação ascendente pelo campo 1.
Queria que esse SQL fosse utilizado em um Cursor e, assim, evitaria a criação de uma tabela temporária... ainda estou batendo cabeça... hehe... qualquer idéia ajuda muito!
Valeu!
Abs.
Diego_Mello
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 229
Registrado em: Sex, 05 Set 2008 2:59 pm
Localização: Igrejinha - RS
Diego Mello
Igrejinha - RS
www.twitter.com/diegolmello

cara...

tenta fazer algo assim...

Selecionar tudo

SELECT a.codpai codpai
			,b.no_pais descricao
			,SUM(a.fobatu) acum_fob_ano_atu
			,SUM(a.fobatu) * 100 /*/ TOT_ACUM_FOB_ANO_ATU ACUM_PART_ANO_ATU*/
			,SUM(a.fobant) acum_fob_ano_ant
			,SUM(a.fobant) * 100 /*/ TOT_ACUM_FOB_ANO_ANT ACUM_PART_ANO_ANT*/
			,REPLACE(to_char(decode(SUM(a.fobant), 0, 0, (SUM(a.fobatu) - SUM(a.fobant)) / SUM(a.fobant) * 100), '999D99')
							,'#######'
							,NULL) acum_var
			,(SUM(a.fobatu) - SUM(a.fobmat)) mês_fob_ano_atu
			,(SUM(a.fobatu) - SUM(a.fobmat)) * 100 /*/ TOT_mês_FOB_ANO_ATU mês_PART_ANO_ATU*/
			,(SUM(a.fobant) - SUM(a.fobman)) mês_fob_ano_ant
			,(SUM(a.fobant) - SUM(a.fobman)) * 100 /*/ TOT_mês_FOB_ANO_ANT mês_PART_ANO_ANT*/
			,REPLACE(to_char(decode((SUM(a.fobant) - SUM(a.fobman))
														 ,0
														 ,0
														 ,((SUM(a.fobatu) - SUM(a.fobmat)) - (SUM(a.fobant) - SUM(a.fobman))) /
															(SUM(a.fobant) - SUM(a.fobman)) * 100)
											,'999D99')
							,'#######'
							,NULL) mês_var
      ,SUM(a.fobatu) ordem
	FROM bd.bcepap    a
			,bd.t200_pais b
 WHERE a.codpai = b.co_pais
	 AND a.codpai <> '990'
 GROUP BY a.codpai
				 ,b.no_pais
UNION
SELECT a.codpai codpai
			,b.no_pais descricao
			,SUM(a.fobatu) acum_fob_ano_atu
			,SUM(a.fobatu) * 100 /*/ TOT_ACUM_FOB_ANO_ATU ACUM_PART_ANO_ATU*/
			,SUM(a.fobant) acum_fob_ano_ant
			,SUM(a.fobant) * 100 /*/ TOT_ACUM_FOB_ANO_ANT ACUM_PART_ANO_ANT*/
			,REPLACE(to_char(decode(SUM(a.fobant), 0, 0, (SUM(a.fobatu) - SUM(a.fobant)) / SUM(a.fobant) * 100), '999D99')
							,'#######'
							,NULL) acum_var
			,(SUM(a.fobatu) - SUM(a.fobmat)) mês_fob_ano_atu
			,(SUM(a.fobatu) - SUM(a.fobmat)) * 100 /*/ TOT_mês_FOB_ANO_ATU mês_PART_ANO_ATU*/
			,(SUM(a.fobant) - SUM(a.fobman)) mês_fob_ano_ant
			,(SUM(a.fobant) - SUM(a.fobman)) * 100 /*/ TOT_mês_FOB_ANO_ANT mês_PART_ANO_ANT*/
			,REPLACE(to_char(decode((SUM(a.fobant) - SUM(a.fobman))
														 ,0
														 ,0
														 ,((SUM(a.fobatu) - SUM(a.fobmat)) - (SUM(a.fobant) - SUM(a.fobman))) /
															(SUM(a.fobant) - SUM(a.fobman)) * 100)
											,'999D99')
							,'#######'
							,NULL) mês_var
       999999999 ordem
	FROM bd.bcepap    a
			,bd.t200_pais b
 WHERE a.codpai = b.co_pais
	 AND a.codpai = '990'
 GROUP BY a.codpai
				 ,b.no_pais
         ORDER BY ordem, 1,2,3,4
;
você cria uma pseudo-coluna chamada ordem... na primeira parte do union você coloca a coluna que você deseja... na segunda parte coloca um valor que você sabe que será o último...

então você coloca um único order by, ordenando por outras colunas também...
vê se isso dá certo...

valeu!!
thiago_r_f
Rank: Programador Pleno
Rank: Programador Pleno
Mensagens: 43
Registrado em: Qui, 17 Abr 2008 4:02 pm
Localização: Rio de Janeiro - RJ
O Backup é meu pastor e nada me faltará!
Thiago Rodrigues de Farias

Valeu Diego!!!
Cara, a dica q tu deu me ajudou muito aqui, pois eu precisava empurrar um conjunto de dados para o fim da fila para que eles não fossem exibidos em um relatório que ia até a 10ª posição ordenada de maneira decrescente por um valor. Joguei esse valor como zero no conjunto de dados q eu queria no fim e usei o valor existente nos registros que interessavam para a coluna ORDEM (conforme tua dica).

Pro meu caso já está resolvido, mas outras idéias são bem-vindas!

está aí o código:

Selecionar tudo

      SELECT A.CODPAI CODPAI, B.NO_PAIS DESCRICAO,
             SUM(A.FOBATU) ACUM_FOB_ANO_ATU, 
             SUM(A.FOBATU) * 100 /*/ TOT_ACUM_FOB_ANO_ATU ACUM_PART_ANO_ATU*/,
             SUM(A.FOBANT) ACUM_FOB_ANO_ANT, 
             SUM(A.FOBANT) * 100 /*/ TOT_ACUM_FOB_ANO_ANT ACUM_PART_ANO_ANT*/, 
             REPLACE( TO_CHAR( DECODE(SUM(A.FOBANT),0,0,
                    (SUM(A.FOBATU) - SUM(A.FOBANT)) / SUM(A.FOBANT) * 100)  ,'999D99'), '#######', NULL) ACUM_VAR, 
             (SUM(A.FOBATU) - SUM(A.FOBMAT)) mês_FOB_ANO_ATU, 
             (SUM(A.FOBATU) - SUM(A.FOBMAT)) * 100 /*/ TOT_mês_FOB_ANO_ATU mês_PART_ANO_ATU*/, 
             (SUM(A.FOBANT) - SUM(A.FOBMAN)) mês_FOB_ANO_ANT, 
             (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100 /*/ TOT_mês_FOB_ANO_ANT mês_PART_ANO_ANT*/,
             REPLACE( TO_CHAR( DECODE((SUM(A.FOBANT) - SUM(A.FOBMAN)),0,0,
                   ((SUM(A.FOBATU) - SUM(A.FOBMAT)) - (SUM(A.FOBANT) - SUM(A.FOBMAN))) / 
                    (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100) ,'999D99'), '#######', NULL) mês_VAR,
             SUM(A.FOBATU) AS ORDEM
       FROM BD.BCEPAP A, BD.T200_PAIS B
      WHERE A.CODPAI = B.CO_PAIS
        AND A.CODPAI <> '990'
      GROUP BY A.CODPAI, B.NO_PAIS
      UNION
      SELECT A.CODPAI CODPAI, B.NO_PAIS DESCRICAO,
             SUM(A.FOBATU) ACUM_FOB_ANO_ATU, 
             SUM(A.FOBATU) * 100 /*/ TOT_ACUM_FOB_ANO_ATU ACUM_PART_ANO_ATU*/,
             SUM(A.FOBANT) ACUM_FOB_ANO_ANT, 
             SUM(A.FOBANT) * 100 /*/ TOT_ACUM_FOB_ANO_ANT ACUM_PART_ANO_ANT*/, 
             REPLACE( TO_CHAR( DECODE(SUM(A.FOBANT),0,0,
                    (SUM(A.FOBATU) - SUM(A.FOBANT)) / SUM(A.FOBANT) * 100)  ,'999D99'), '#######', NULL) ACUM_VAR, 
             (SUM(A.FOBATU) - SUM(A.FOBMAT)) mês_FOB_ANO_ATU, 
             (SUM(A.FOBATU) - SUM(A.FOBMAT)) * 100 /*/ TOT_mês_FOB_ANO_ATU mês_PART_ANO_ATU*/, 
             (SUM(A.FOBANT) - SUM(A.FOBMAN)) mês_FOB_ANO_ANT, 
             (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100 /*/ TOT_mês_FOB_ANO_ANT mês_PART_ANO_ANT*/,
             REPLACE( TO_CHAR( DECODE((SUM(A.FOBANT) - SUM(A.FOBMAN)),0,0,
                   ((SUM(A.FOBATU) - SUM(A.FOBMAT)) - (SUM(A.FOBANT) - SUM(A.FOBMAN))) / 
                    (SUM(A.FOBANT) - SUM(A.FOBMAN)) * 100) ,'999D99'), '#######', NULL) mês_VAR,
             0 AS ORDEM
       FROM BD.BCEPAP A, BD.T200_PAIS B
      WHERE A.CODPAI = B.CO_PAIS
        AND A.CODPAI = '990'
      GROUP BY A.CODPAI, B.NO_PAIS
      ORDER BY ORDEM DESC;
Valeu a todos!!!
Abs
Diego_Mello
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 229
Registrado em: Sex, 05 Set 2008 2:59 pm
Localização: Igrejinha - RS
Diego Mello
Igrejinha - RS
www.twitter.com/diegolmello

uma variação para isso é usar um decode como pseudo-coluna...

por exemplo...
na tabela marcas_produtos eu quero trazer as marcas da seguinte forma:
1, 16, 3, (e todo o resto)...

porém não há uma forma apenas com order by de fazê-lo...

logo, faz-se um decode...

Selecionar tudo

SELECT m.codigo_marca
      ,DECODE(m.codigo_marca, 1, 1, 16, 2, 3, 3) ordem
  FROM marcas_produtos m
 ORDER BY ordem;

Selecionar tudo

CODIGO_MARCA      ORDEM
------------------        ----------
           1                      1
          16                     2
           3                      3
           2 
           6 
           5 
           0 
          12 
          11 
           9 
          10 
          13 
           4 
           7 
           8 
          14 
          15
thiago_r_f
Rank: Programador Pleno
Rank: Programador Pleno
Mensagens: 43
Registrado em: Qui, 17 Abr 2008 4:02 pm
Localização: Rio de Janeiro - RJ
O Backup é meu pastor e nada me faltará!
Thiago Rodrigues de Farias

Pois é Diego, tu deu mais outra luz aí!
Dessa maneira, poderia ser criada uma pseudo-coluna definindo tipos de dados distintos a serem ordenados e, posteriormente, seus valores.

Selecionar tudo

SELECT 1 as tipo,
            SUM(valor) as valor
  FROM tabela
 WHERE cod <= '3'
 UNION
SELECT 2 as tipo,
            SUM(valor) as valor
  FROM tabela
 WHERE cod > '3'
 ORDER BY tipo, valor;


------------------------
# Resultando em:
------------------------
TIPO  |  VALOR  |  COD
------------------------
  1         10        1
  1         20        2
  1         30        3
  2         10        4
  2         20        5
  2         30        6
------------------------
Gostei! Dá pra se virar bem sem um order num UNION dessas maneiras! hehehe!
Abs.
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 10 visitantes