Página 1 de 1

Dúvida em restrição com faixas de valores

Enviado: Seg, 29 Dez 2008 2:59 pm
por Diego_Mello
Galera...olha só...

Tenho que criar um relatório no qual tenho que restringir os valores da seguinte forma:

1 a 400 reais

401 a 600

601 a 800

801 a 1000

1001 a 1200

Acima de 1201...

Fiz uma gambiarra aqui :o e ficou assim...

Selecionar tudo

		 AND
							 ((&intervalo = 6 AND nfs.nfs_vltot > 1201) OR
								nfs.nfs_vltot BETWEEN
								decode(&intervalo, 1, 1, 2, 401, 3, 601, 4, 801, 5, 1001) AND
								decode(&intervalo, 1, 400, 2, 600, 3, 800, 4, 1000, 5, 1200)) 
Alguém pode aperfeiçoar?

Valeu!

Enviado: Seg, 29 Dez 2008 5:06 pm
por Trevisolli
Brother,

Daria pra fazer com UNION com as faixas, mudando uma coluna da querie, sendo o teu nro de quebra, ou, fazendo agrupamento pelo teu sequencial, caso o tenha.

qualquer coisa, manda pra gente.

Enviado: Ter, 30 Dez 2008 8:38 am
por Diego_Mello
Era isso mesmo que eu precisava...

Não tinha considerado o fato de ter que mostrar a que faixa de valores o registro pertencia...
Logo, da forma que eu estava fazendo, me complicaria para considerar...

Valeu! :-o

Enviado: Sex, 02 Jan 2009 5:41 am
por Toad
Legal, cara!
Assim que tudo der certinho mesmo, posta pra gente aqui como ficou a solução final, por favor?

Enviado: Ter, 06 Jan 2009 2:54 pm
por Diego_Mello
Tranquilo, brother...

Em resumo, ficou assim...

Selecionar tudo

 SELECT faixa
			,ordem
	FROM (
				--// INTERVALO = 1
				SELECT '1 a 400' faixa
							 ,1 ordem
					FROM . . .
				 WHERE (:p_intervalo = 1 OR :p_intervalo = 7)
							 AND round(nfs.nfs_vltot) >= 1
							 AND round(nfs.nfs_vltot) <= 400
				UNION ALL
				
				--//INTERVALO = 2
				SELECT '401 a 600' faixa
							,2 ordem
					FROM . . .
				 WHERE (:p_intervalo = 2 OR :p_intervalo = 7)
							 AND round(nfs.nfs_vltot) >= 401
							 AND round(nfs.nfs_vltot) <= 600
				UNION ALL
				
				--// INTERVALO = 3
				SELECT '601 a 800' faixa
							,3 ordem
					FROM . . .
				 WHERE (:p_intervalo = 3 OR :p_intervalo = 7)
							 AND round(nfs.nfs_vltot) >= 601
							 AND round(nfs.nfs_vltot) <= 800
				UNION ALL
				
				--//INTERVALO = 4
				SELECT '801 a 1000' faixa
							,4 ordem
					FROM . . .
				 WHERE (:p_intervalo = 4 OR :p_intervalo = 7)
							 AND round(nfs.nfs_vltot) >= 801
							 AND round(nfs.nfs_vltot) <= 1000
				UNION ALL
				
				--// INTERVALO = 5
				SELECT '1001 a 1200' faixa
							,5 ordem
					FROM . . .
				 WHERE (:p_intervalo = 5 OR :p_intervalo = 7)
							 AND round(nfs.nfs_vltot) >= 1001
							 AND round(nfs.nfs_vltot) <= 1200
				UNION ALL
				
				--//INTERVALO = 6
				SELECT 'Maior que 1201' faixa
							,6 ordem
					FROM . . .
				 WHERE (:p_intervalo = 6 OR :p_intervalo = 7)
							 AND round(nfs.nfs_vltot) >= 1201) nft
 ORDER BY . . . 
Agradeço a ajuda!

Enviado: Ter, 06 Jan 2009 4:47 pm
por dr_gori
Também é possível usar CASE WHEN. Daí não precisa de um monte de UNION ALL.

Algo assim:

Selecionar tudo

SELECT
  CAMPO
, VALOR
, CASE WHEN valor >=  0  AND valor <=100 THEN  1
       wHEN valor > 100  AND valor <=200 THEN  2
       wHEN valor > 200  AND valor <=400 THEN  3
       wHEN valor > 400  AND valor <=800 THEN  4
       wHEN valor > 800  AND valor <=1500 THEN 5
       wHEN valor > 1500 AND valor <=5000 THEN 6
  END faixa     
FROM TABELA
neste caso, vai criar apenas com o NÚMERO da faixa.
Mas depois você simplesmente "traduz" esse número para um número que o usuário entenda.
Tipo:
faixa 1 = Entre 0 e 100
faixa 2 = Entre 100 e 200
faixa 3 = Entre 200 e 400
etc

Enviado: Qua, 07 Jan 2009 7:13 am
por Diego_Mello
É que eu preciso, além de trazer no select, restringir por essa faixa de valores...
Logo, voltamos a minha dúvida inicial... :(

Enviado: Qua, 07 Jan 2009 8:10 am
por dr_gori
Realmente, no meu caso ele apenas MOSTRA qual faixa.

Mas tem uma coisa: Caso seu usuário escolha 7 (todos), ele vai rodar várias vezes a consulta e fazer UNIONs... Teoricamente isso não é necessário, pois dá pra fazer tudo isso mais facilmente.

Outra coisa: não é necessário colocar ROUND, pois isso provavelmente vai gerar muito mais custo pra sua consulta.

Você poderia combinar as duas coisas da seguinte forma:

Selecionar tudo

SELECT
  CAMPO
, VALOR
, CASE WHEN valor >=  0  AND valor <=100 THEN  '0 a 400'
       wHEN valor > 100  AND valor <=200 THEN  '400 a 600'
       wHEN valor > 200  AND valor <=400 THEN  '600 a 800'
       wHEN valor > 400  AND valor <=800 THEN  'etc...'
       wHEN valor > 800  AND valor <=1500 THEN 'etc..'
       wHEN valor > 1500 AND valor <=5000 THEN 'etc..'
  END faixa     
FROM TABELA
WHERE  :p_intervalo = 7 
   OR (:p_intervalo = 1 AND nfs.nfs_vltot>=0   AND nfs.nfs_vltot<=400)
   OR (:p_intervalo = 2 AND nfs.nfs_vltot>400  AND nfs.nfs_vltot<=600)
   OR (:p_intervalo = 3 AND nfs.nfs_vltot>600  AND nfs.nfs_vltot<=800)
   .
   .
   .
   etc 

Dessa forma, ele MOSTRA qual faixa caiu no CASE WHEN acima.
E também filtra APENAS a faixa informada no parâmetro! Muito mais performático! :-)

Enviado: Qua, 07 Jan 2009 12:50 pm
por Diego_Mello
Brother!
Alterei a query, conforme tua dica, porém a performance, por incrível que pareça, piorou o.0
A query completa executava em 36seg antes da alteração.
Depois dela, passou a executar em 50seg.

Em resumo, ficou assim...

Selecionar tudo

SELECT
CASE
	WHEN nfs.nfs_vltot >= 0 AND nfs.nfs_vltot <= 400 THEN 1
	WHEN nfs.nfs_vltot > 400 AND nfs.nfs_vltot <= 600 THEN 2
	WHEN nfs.nfs_vltot > 600 AND nfs.nfs_vltot <= 800 THEN 3
	WHEN nfs.nfs_vltot > 800 AND nfs.nfs_vltot <= 1000 THEN 4
	WHEN nfs.nfs_vltot > 1000 AND nfs.nfs_vltot <= 1200 THEN 5
	WHEN nfs.nfs_vltot > 1200 THEN 6
END ordem
FROM tabela
WHERE     (&p_intervalo = 7
               OR (&p_intervalo = 1 AND nfs.nfs_vltot >= 0 AND nfs.nfs_vltot <= 400)
               OR (&p_intervalo = 2 AND nfs.nfs_vltot > 400 AND nfs.nfs_vltot <= 600)
               OR (&p_intervalo = 3 AND nfs.nfs_vltot > 600 AND nfs.nfs_vltot <= 800) 
               OR (&p_intervalo = 4 AND nfs.nfs_vltot > 800 AND nfs.nfs_vltot <= 1000) 
               OR (&p_intervalo = 5 AND nfs.nfs_vltot > 1000 AND nfs.nfs_vltot <= 1200) 
               OR (&p_intervalo = 6 AND nfs.nfs_vltot > 1200)) 

Enviado: Qua, 07 Jan 2009 1:11 pm
por dr_gori
Pro intervalo 7 ou pros outros ?

Enviado: Qua, 07 Jan 2009 1:12 pm
por Diego_Mello
intervalo 7

Dúvida em restrição com faixas de valores

Enviado: Dom, 11 Jan 2009 12:36 am
por margaridi
Creio que assim ficará mais leve:

Selecionar tudo

select nfs.nfs_vltot
,      decode(trunc((nfs.nfs_vltot-0.01)/200),0,1,1,1,2,2,3,3,4,4,5,5,6) intervalo
,      decode(decode(trunc((nfs.nfs_vltot-0.01)/200),0,1,1,1,2,2,3,3,4,4,5,5,6),
              1, '    1  a   400',
              2, '  401  a   600', 
              3, '  601  a   800', 
              4, '  801  a  1000', 
              5, ' 1001  a  1200','Acima de  1200')
from   nfs
where  &intervalo = 7
or     &intervalo = decode(trunc((nfs.nfs_vltot-0.01)/200),0,1,1,1,2,2,3,3,4,4,5,5,6)

Enviado: Seg, 12 Jan 2009 9:04 am
por Diego_Mello
Ficou melhor agora ^^

Obrigado a todos pela ajuda! :-o