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

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
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

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!
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

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.
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

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
Avatar do usuário
Toad
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 253
Registrado em: Sex, 18 Nov 2005 2:14 pm
Localização: Seattle, WA
Contato:
Matheus Gonçalves
matheus.dev
twitter.com/developer__c

Legal, cara!
Assim que tudo der certinho mesmo, posta pra gente aqui como ficou a solução final, por favor?
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

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!
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

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

É que eu preciso, além de trazer no select, restringir por essa faixa de valores...
Logo, voltamos a minha dúvida inicial... :(
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

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! :-)
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

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)) 
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Pro intervalo 7 ou pros outros ?
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

intervalo 7
margaridi
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 21
Registrado em: Ter, 08 Abr 2008 11:09 am
Localização: Curitiba - PR
Contato:
----------------------------
Margaridi, Marco Aurélio
www.margaridi.com

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)
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

Ficou melhor agora ^^

Obrigado a todos pela ajuda! :-o
Responder
  • Informação
  • Quem está online

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