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