Pessoal, eu estou com uma situação onde devo selecionar várias coisas de uma tabela, com uma série de restrições. Mas uma delas está me atrasando: eu tenho que verificar um atributo “ATRIB2” e, se ele for diferente de 0, fazer um join com uma tabela de controle de usuários por ele. Algo assim:
select *
from
tabela1,
tabela_controle controle1,
tabela_controle controle2
where
tabela1.atrib1 = controle1.atrib
and tabela1.atrib2 = controle2.atrib // somente se for != 0!!!
Alguém pode me dar uma ajuda nessa? Já pesquisei pelas cláusulas IF, DECODE e CASE, mas nenhuma delas me pareceu ser utilizável neste caso…
Hm, talvez eu não tenha me expressado bem: Eu preciso que as que tem
tabela1.atrib2 == 0
retornem, mas sem filtrar pelo
and tabela1.atrib2 = controle2.atrib
Em algoritmo, seria algo como…
select *
from
tabela1,
tabela_controle controle1,
tabela_controle controle2
where
tabela1.atrib1 = controle1.atrib
if tabela1.atrib2 != 0
and tabela1.atrib2 = controle2.atrib // filtra
else
// não filtra
S
sjoaquim
Não sei se entendi, mas você está querendo que retorne um número variável de colunas dependendo de uma condição? Isso não é possível em um banco de dados relacional…
O que você pode é fazer o join das três tabelas e fazer o teste de “se for diferente de zero, processa colunas da tabela controle2” na sua própria aplicação.
G
gomesrod
...
and (tabela1.atrib2 = 0 or tabela1.atrib2 = controle2.atrib)
M
Marcelo_FS
Não exatamente: o número de colunas é sempre o mesmo.
select
tabela1.id,
tabela1.atrib1,
tabela1.atrib2
from
tabela1,
tabela_controle controle1,
tabela_controle controle2
where
tabela1.atrib1 = controle1.atrib
if tabela1.atrib2 != 0
and tabela1.atrib2 = controle2.atrib // filtra
else
// não filtra
O que eu quero é que, se atrib2!=0, seja feito um filtro por ele; caso atrib2==0, não seja feito o filtro por ele (somente por atrib1). Fazer o controle na aplicação está realmente fora de cogitação, já que são algumas centenas de milhares de colunas… :?
M
Marcelo_FS
gomesrod:
...
and (tabela1.atrib2 = 0 or tabela1.atrib2 = controle2.atrib)
Quase! O problema de fazer isso é que, se tabela1.atrib2==0, ocorrerá tabela1 X controle2… retornando um monte de resultados repetidos. Distinct não ajuda, já que tenho alguns campos CLOB…
A
ajfilho
Bom, eu não testei o código, mas acredito que o caminho deve ser por aqui!
select *
from tabela1, tabela_controle controle1, tabela_controle controle2
where tabela1.atrib1 = controle1.atrib
case
when tabela1.atrib2 <> 0 then tabela1.atrib2 = controle2.atrib
else null -- Não faz nada
end
Quando o atributo for !=0 irá subtrair o registro da query principal.
S
sjoaquim
Interessante!
Essa função é do SQL ANSI? Tem em todos os SGBDs?
G
gomesrod
MarceloS:
gomesrod:
...
and (tabela1.atrib2 = 0 or tabela1.atrib2 = controle2.atrib)
Quase! O problema de fazer isso é que, se tabela1.atrib2==0, ocorrerá tabela1 X controle2… retornando um monte de resultados repetidos. Distinct não ajuda, já que tenho alguns campos CLOB… :(
Não entendi!
O que acontece de errado?
S
sjoaquim
Que tal isso aqui:
select
tabela1.id,
tabela1.atrib1,
tabela1.atrib2
from
tabela1
where
tabela1.id in
(select
tabela1.id
from
tabela1,
tabela_controle controle1,
tabela_controle controle2
where
tabela1.atrib1 = controle1.atrib
and tabela1.atrib2 <> 0
and tabela1.atrib2 = controle2.atrib)
or
tabela1.id in
(select
tabela1.id
from
tabela1,
tabela_controle controle1
where
tabela1.atrib1 = controle1.atrib
and tabela1.atrib2 = 0)
M
Marcelo_FS
Pessoal, consegui resolver assim:
select *
from
tabela1,
tabela_controle controle1,
tabela_controle controle2
where
tabela1.atrib1 = controle1.atrib
and (
tabela1.atrib2 = 0
or
tabela1.atrib2 = controle2.atrib
)
and controle1.user = 1 // usuário do sistema, faltou mencionar, my fault
and controle2.user = controle1.user
Tinha esquecido de especificar o número do usuário no sistema, e por isso que não tinha conseguido fazer a dica do gomesrod funcionar… :oops:
Valeu pela ajuda de todos!!
M
matheus_germiniani
ola Pessoal to com uma duvida eu to executando um select pra fazer um sum na tabela de multas so que qando nao tem multa no periodo que to pedindo ele nao retorna nada ai nao aparece nada no quikreport ele era que aparecer zero quando for null so que nao consigo fazer sera que alguem pode me ajudar?
eu to usando oseguinte comando so que nao funciona
select
V.CODIGOEMPRESA AS EMPRESA,
SUM(M.VALORTOTALMULTA)AS TOTAL_M,
case
when SUM(M.VALORTOTALMULTA) <> 0 then SUM(M.VALORTOTALMULTA)
when SUM(M.VALORTOTALMULTA) = 0 then 0
when SUM(M.VALORTOTALMULTA) = null then 0
else 1 - 1 end
from
dvs_multa M,
FRT_CADVEICULOS V
WHERE
V.CODIGOVEIC = M.CODIGOVEIC
–AND V.CODIGOEMPRESA = 2
AND M.DATAVECTOMULTA BETWEEN ‘01-JUN-2009’ AND '30-JUN-2009’
GROUP BY
V.CODIGOEMPRESA
P
pmlm
hmmm…
Assim não resolve?
select V.CODIGOEMPRESA AS EMPRESA,
SUM(nvl(M.VALORTOTALMULTA,0)) AS TOTAL_M
FROM dvs_multa M, FRT_CADVEICULOS V
WHERE V.CODIGOVEIC = M.CODIGOVEIC
AND M.DATAVECTOMULTA BETWEEN '01-JUN-2009' AND '30-JUN-2009'
GROUP BY V.CODIGOEMPRESA
M
matheus_germiniani
vo tentar deste jeito… ai ja respondo!!!
vlw…
M
matheus_germiniani
fiz como vc havia me falado mas ficou do mesmo jeito qdo nao tem dado a ser puchado ele nao traz nada, so que na aplicaçao como esta dentro de outra consultas ai sai tudo embranco por causa disso… tipo ao invez de nao parecer registro teria q colocar o zero.
P
pmlm
Provavelmente o que queres então é fazer um outer join com a tabela dvs_multa.
select V.CODIGOEMPRESA AS EMPRESA,
SUM(nvl(M.VALORTOTALMULTA,0)) AS TOTAL_M
FROM FRT_CADVEICULOS V outer dvs_multa M
WHERE V.CODIGOVEIC = M.CODIGOVEIC
AND M.DATAVECTOMULTA BETWEEN '01-JUN-2009' AND '30-JUN-2009'
GROUP BY V.CODIGOEMPRESA
M
matheus_germiniani
Muito obrigo… deu certo!!!
Te devo uma… fico bem legal o que eu precisava…