- Este tópico contém 9 respostas, 3 vozes e foi atualizado pela última vez 15 anos, 6 meses atrás por
luan.
-
AutorPosts
-
11 de setembro de 2010 às 1:28 am #96035
luan
ParticipanteBoa noite galera, meu primeiro post aqui, estou com uma duvida que não achei ainda uma solução, sou meio iniciante em PL/SQL, trabalho mais com desenvolvimento java…
Vamos lá, a dúvida é a seguinte:
tenho a seguinte query:SELECT DISTINCT A.DTAGENDA
FROM AGENDA_DETAIL A
JOIN AGENDA_DADO B ON ( A.IDAGENDADADO = B.IDAGENDADADO )
JOIN AGENDA_SALA C ON ( B.IDSALA = C.IDSALA )
WHERE A.FLAG = ‘DISPONIVEL’ AND
A.STATUS = ‘ATIVADO’ AND
C.IDPRESTADORDETAIL = 1421 AND
B.IDMEDICOESPECIALIDADE = 400 AND
B.IDTUSS IN(2810,2825);por exemplo nesse caso, a consulta me retorna o dia 20/09/2010, mas para esse dia eu tenho apenas disponível agenda para o código 2810 mas não para o 2825.
precisava retornar os dias apenas que tenha agenda disponivel para os 2 codigos no mesmo dia e não apenas para um ou outro.Não sei se consegui explicar direito.
Muito obrigado galera, grande abraço!
11 de setembro de 2010 às 3:12 am #96036burga
ParticipanteExistem várias maneiras diferentes de se fazer isto, segue três delas:
SELECT DISTINCT DTAGENDA
FROM (
SELECT A.DTAGENDA
FROM AGENDA_DETAIL A
JOIN AGENDA_DADO B ON ( A.IDAGENDADADO = B.IDAGENDADADO )
JOIN AGENDA_SALA C ON ( B.IDSALA = C.IDSALA )
WHERE A.FLAG = 'DISPONIVEL' AND
A.STATUS = 'ATIVADO' AND
C.IDPRESTADORDETAIL = 1421 AND
B.IDMEDICOESPECIALIDADE = 400 AND
B.IDTUSS = 2810INTERSECT
SELECT A.DTAGENDA
FROM AGENDA_DETAIL A
JOIN AGENDA_DADO B ON ( A.IDAGENDADADO = B.IDAGENDADADO )
JOIN AGENDA_SALA C ON ( B.IDSALA = C.IDSALA )
WHERE A.FLAG = 'DISPONIVEL' AND
A.STATUS = 'ATIVADO' AND
C.IDPRESTADORDETAIL = 1421 AND
B.IDMEDICOESPECIALIDADE = 400 AND
B.IDTUSS = 2825);ou
SELECT DISTINCT A.DTAGENDA
FROM AGENDA_DETAIL A
WHERE EXISTS (
SELECT 1
FROM AGENDA_DETAIL D
JOIN AGENDA_DADO B ON ( D.IDAGENDADADO = B.IDAGENDADADO )
JOIN AGENDA_SALA C ON ( B.IDSALA = C.IDSALA )
WHERE A.FLAG = 'DISPONIVEL' AND
D.STATUS = 'ATIVADO' AND
C.IDPRESTADORDETAIL = 1421 AND
B.IDMEDICOESPECIALIDADE = 400 AND
B.IDTUSS = 2810 AND
A.DTAGENDA = D.DTAGENDA)
AND EXISTS (
SELECT 1
FROM AGENDA_DETAIL D
JOIN AGENDA_DADO B ON ( D.IDAGENDADADO = B.IDAGENDADADO )
JOIN AGENDA_SALA C ON ( B.IDSALA = C.IDSALA )
WHERE A.FLAG = 'DISPONIVEL' AND
D.STATUS = 'ATIVADO' AND
C.IDPRESTADORDETAIL = 1421 AND
B.IDMEDICOESPECIALIDADE = 400 AND
B.IDTUSS = 2825 AND
A.DTAGENDA = D.DTAGENDA);ou
SELECT DTAGENDA
FROM (
SELECT DISTINCT A.DTAGENDA, B.IDTUSS
FROM AGENDA_DETAIL A
JOIN AGENDA_DADO B ON ( A.IDAGENDADADO = B.IDAGENDADADO )
JOIN AGENDA_SALA C ON ( B.IDSALA = C.IDSALA )
WHERE A.FLAG = 'DISPONIVEL' AND
A.STATUS = 'ATIVADO' AND
C.IDPRESTADORDETAIL = 1421 AND
B.IDMEDICOESPECIALIDADE = 400 AND
(B.IDTUSS = 2810 OR B.IDTUSS = 2825))
GROUP BY DTAGENDA
HAVING COUNT(*) > 1;Não sei qual tem o pior custo, todas parecem ter um desempenho bem baixo… 😆
13 de setembro de 2010 às 1:37 am #96040luan
ParticipanteBoa noite, opa valeu Burga, amanha no trampo eu testo e posto os resultados!
Muito Obrigado
Abraços
13 de setembro de 2010 às 3:38 pm #96042luan
ParticipanteBom dia galera, valeu Burga, optei pela terceira opção que teve um desempenho melhor…
A princípio o custo ficou em 11380, mas depois de criar 1 index o custo caiu para 11 executado em 0,37400001 segundos ..Muito obrigado
Abraços!
13 de setembro de 2010 às 5:01 pm #96044jspaulonci
ParticipanteParabens Burga
13 de setembro de 2010 às 9:59 pm #96055luan
ParticipanteBoa tarde galera, surgiu uma outra dúvida que talvez seja util para outros usuários também, seguinte eu preciso gerar um ‘ where ‘ dinamicamente..
procedure finddiaslivres(
P_IDPRESTADORDETAIL IN PRESTADOR_DETAIL.IDDETAIL%TYPE,
P_IDMEDICOESPECIALIDADE IN AGENDA_DADO.IDMEDICOESPECIALIDADE%TYPE,
P_ESPECIALIDADE IN AGENDA_DADO.IDMEDICOESPECIALIDADE%TYPE,
P_ARRAYIDTUSS IN NUMBER_ARRAY,
P_CURSOR OUT NOCOPY TYPES.REF_CURSOR)ASV_CONTADOR NUMBER := 0;
V_I NUMBER := 0;
V_QUERYCOMPL VARCHAR2(100);BEGIN
V_CONTADOR := P_ARRAYIDTUSS.COUNT;
WHILE ( V_I V_I ) THEN
V_QUERYCOMPL := V_QUERYCOMPL || ‘ OR B.IDTUSS =’;
END IF;
END LOOP;IF ( P_IDPRESTADORDETAIL > 0 AND P_IDMEDICOESPECIALIDADE > 0 ) THEN
OPEN P_CURSOR FOR SELECT DTAGENDA FROM ( SELECT DISTINCT A.DTAGENDA, B.IDTUSS FROM AGENDA_DETAIL A JOIN AGENDA_DADO B ON ( A.IDAGENDADADO = B.IDAGENDADADO ) JOIN AGENDA_SALA C ON ( B.IDSALA = C.IDSALA ) WHERE A.FLAG = 'DISPONIVEL' AND A.STATUS = 'ATIVADO' AND C.IDPRESTADORDETAIL = 1421 AND B.IDMEDICOESPECIALIDADE = 400 AND B.IDTUSS = V_QUERYCOMPL) GROUP BY DTAGENDA HAVING COUNT(*) > 1;os idtuss eu enviei para procedure como array pois não sei a quantidade que será escolhida pelo usuário, mas acontece o seguinte, quando eu itero ele e vou concatenando os OR B.IDTUSS + a posição no array que seria outro numero, quando a query é executada da o erro:
ORA-01722: número inválido.
Creio que seja porque a variavel v_querycompl é um varchar, e o B.IDTUSS seria um number, mas nesse caso como eu faria para gerar isso dinamicamente?Muito obrigado novamente…
13 de setembro de 2010 às 10:27 pm #96056burga
ParticipanteNa verdade você deve montar a consulta inteira dentro do V_QUERYCOMPL, como um varchar2 e depois chamá-la no OPEN P_CURSOR FOR:
OPEN P_CURSOR FOR V_QUERYCOMPL;
LOOP
FETCH P_CURSOR INTO ...;
EXIT WHEN P_CURSOR%NOTFOUND;
-- seu processamento
END LOOP;14 de setembro de 2010 às 12:09 am #96058luan
ParticipanteObrigado novamente Burga, vc é fera, que bom ter o privilégio de participar de um forum com experts como esse….
Agora está 100% Smile, valeu mesmo…
Abraços!
14 de setembro de 2010 às 5:43 pm #96062burga
ParticipanteSó lembrando que SQL dinâmico é quase um sinônimo de performance ruim, pois na maioria das vezes o Oracle vai ter que executar o hard parsing do seu SQL dinâmico, então é sempre bom (se possível) tentar evitar seu uso.
Outra coisa, eu não prestei muita atenção no seu código e foquei mais na solução do erro, agora que vi melhor, percebi que a consulta que você está gerando é a mesma do começo do tópico, então já vou apontar dois problemas no código que você postou, um de semântica e outro de lógica:
OPEN P_CURSOR FOR
SELECT DTAGENDA
FROM (
SELECT DISTINCT A.DTAGENDA, B.IDTUSS
FROM AGENDA_DETAIL A
JOIN AGENDA_DADO B ON ( A.IDAGENDADADO = B.IDAGENDADADO )
JOIN AGENDA_SALA C ON ( B.IDSALA = C.IDSALA )
WHERE A.FLAG = ‘DISPONIVEL’ AND
A.STATUS = ‘ATIVADO’ AND
C.IDPRESTADORDETAIL = 1421 AND
B.IDMEDICOESPECIALIDADE = 400 AND
B.IDTUSS = V_QUERYCOMPL)
GROUP BY DTAGENDA
HAVING COUNT(*) > 1;Um dos problemas é que você não colocou as condições com B.IDTUSS entre parênteses, sem isso a consulta não vai ser executada da forma que você deseja, uma forma simples de resolver isto é usar o IN ao invés de vários OR (ex.: B.IDTUSS IN (codigo1[,codigoN…]) )…
Outro problema é o HAVING COUNT() > 1, este caso serve apenas para quando você procura datas que possuem em dois IDTUSS, caso sejam três IDTUSS então deve ser HAVING COUNT() > 2, e para N IDTUSS diferentes seria HAVING COUNT(*) > (N-1);
16 de setembro de 2010 às 3:44 pm #96103luan
ParticipantePerfeito burga, corrigi os problemas.
E muito obrigado novamente!!!!Abs bom dia!
-
AutorPosts
- Você deve fazer login para responder a este tópico.