Inner join ou Left outer?

02/08/2010

0

Caros

Estou realizando uma consulta onde o resultado será o seguinte:

Resumidamente!
Usuario, Login, Logout, ini_pausa, fim_pausa

Essas informações estão em tabelas diferentes.
A consulta "funciona" com inner join, mas se o usuário não efetuou pausa (ini_pausa e fim_pausa), ele não é exibido no resultado.
Preciso que esse usuário seja exibido mesmo sem essa informação.

Help! I need somebody, help!
Elton ésqui

Elton ésqui

Responder

Posts

02/08/2010

Tiago Melo

Elton, o inner join é uma clausula que exibe os registros somente quando os registros de usando na clausula "on" existe tanto na tabela pai quanto na tabela filha, sendo assim para que os registros sejam exibidos os campos utilizados em "on" deveram conter exatamente os mesmos valores nas duas tabelas...já o left join dá pra preferencia para a tabela da esquerda, ou seja mesmo que não haja registro na tabela da direita pelo menos os registros da tabela da esquerda serão apresentados...ex:   select p.NomePai, f.NomeFilho from Tabela_Pai p inner join Tabela_Filho f on p.IdPai = f.IdFilho   **nesse exemplo caso não haja um filho correspondente a um pai cadastrado na tabela filho o result set retornará vazio.   select p.NomePai, f.NomeFilho from Tabela_Pai p left outer join Tabela_Filho f on p.IdPai = f.IdFilho     **nesse exemplo mesmo que não haja um filho correspondente a um pai cadastrado na tabela filho, pelo menos o pai que está cadastrado na tabela pai será apresentado isso porque o "join" está dando preferencia para a tabela da esquerda, que é a tabela Tabela_Pai, o mesmo conceito é válido para RIGTH JOIN.
Responder

02/08/2010

Elton ésqui

Bom, tentei usar o LEFT e RIGHT onde entendi que deveria ser, mesmo assim não obtive o resultado desejado.
Segue abaixo como as tabelas estão ligadas.


O que preciso: Exibir o resultado mesmo quando só tenha registro na tabela LIG_CAB (campo: INI_OPER).
Ou seja, independente de exisitir ou não a pausa, deverá mostrar o operador que iniciou a operação (INI_OPER)

Obrigado!

Segue o select utilizado:
SELECT
  V.CODIGO,
  V.NOME,
  L.INI_OPER,
  L.FIM_OPER,
  O.INI_PAUSA,
  O.FIM_PAUSA,
  M.DESCRICAO AS MOTIV_PAUSAS,
  O.DATA AS DATA_PAUSAS,
  L.DATA AS DATA_INI_OPER
FROM
  VROPERAD V
  INNER JOIN OPEPAUSA O ON (V.CODIGO = O.OPERADOR)
  INNER JOIN MPAUSA M ON (O.MOTIVO = M.CODIGO)
  INNER JOIN LIG_CAB L ON (O.OPERADOR = L.OPERADOR)
WHERE
  O.DATA BETWEEN '07/28/2010' AND '08/02/2010' AND
  L.DATA BETWEEN '07/28/2010' AND '08/02/2010'
ORDER BY
  O.DATA
Responder

03/08/2010

Emerson Nascimento

use left join
Responder

03/08/2010

Elton ésqui

Teve um comportamento um tanto estranho.
Se, por exemplo, o cara iniciou a operação ontem, mas não efetuou pausas e iniciou a operação hoje e efetuou pausas, no resultado exibe as pausas de hoje na data de ontem. Estranho!!!

Código Nome Ini. operador Fim operador Iníc.Pausa Fim pausa MOTIV_PAUSAS DATA_PAUSAS DATA_INI_OPER 3.00 Peter Pan 30/07/2010 10:32 30/07/2010 17:36 30/07/2010 10:32 30/07/2010 10:32 BANHEIRO 30/07/2010 00:00 30/07/2010 00:00 3.00 Peter Pan 30/07/2010 10:32 30/07/2010 17:36 30/07/2010 10:32 30/07/2010 10:32 ALMOÇO 30/07/2010 00:00 30/07/2010 00:00 3.00 Peter Pan 03/08/2010 09:27 30/07/2010 17:27 30/07/2010 10:32 30/07/2010 10:32 BANHEIRO 30/07/2010 00:00 03/08/2010 00:00 3.00 Peter Pan 03/08/2010 09:27 30/07/2010 17:27 30/07/2010 10:32 30/07/2010 10:32 ALMOÇO 30/07/2010 00:00 03/08/2010 00:00
Responder

05/08/2010

Emerson Nascimento

as tabelas mais devem ser relacionadas da forma correta:

SELECT
  V.CODIGO,
  V.NOME,
  L.INI_OPER,
  L.FIM_OPER,
  O.INI_PAUSA,
  O.FIM_PAUSA,
  M.DESCRICAO AS MOTIV_PAUSAS,
  O.DATA AS DATA_PAUSAS,
  L.DATA AS DATA_INI_OPER
FROM
  VROPERAD V
  INNER JOIN LIG_CAB L ON (L.OPERADOR = O.OPERADOR)
  LEFT JOIN OPEPAUSA O ON (O.OPERADOR = V.CODIGO and O.DATA = L.DATA)
  LEFT JOIN MPAUSA M ON (M.CODIGO = O.MOTIVO)
WHERE
  L.DATA BETWEEN '07/28/2010' AND '08/02/2010'
ORDER BY
  L.DATA


Responder

10/08/2010

Elton ésqui

Gerou erro!

Não é possível criar expressão de JOIN direito para esta consulta.
Responder

10/08/2010

Elton ésqui

Parece que incluindo tudo vai!

SELECT
  V.CODIGO,
  V.NOME,
  L.INI_OPER,
  L.FIM_OPER,
  O.INI_PAUSA,
  O.FIM_PAUSA,
  M.DESCRICAO AS MOTIV_PAUSAS,
  O.DATA AS DATA_PAUSAS,
  L.DATA AS DATA_INI_OPER
FROM
  OPEPAUSA O
  FULL OUTER JOIN LIG_CAB L ON (L.OPERADOR = O.OPERADOR)
  AND (O.DATA = L.DATA)
  LEFT OUTER JOIN VROPERAD V ON (O.OPERADOR = V.CODIGO)
  LEFT OUTER JOIN MPAUSA M ON (M.CODIGO = O.MOTIVO)
WHERE
  L.DATA BETWEEN '07/28/2010' AND '08/02/2010'
ORDER BY
  L.DATA


Estou testando ainda!!!
Responder

10/08/2010

Elton ésqui

Da maneira anterior, assim como a que está logo abaixo, estão mostrando o resultado como deveria, se não fosse um detalhe:
Quando o operador não tem pausas, no resultado não exibe o código e nome dele.

SELECT
  V.CODIGO,
  V.NOME,
  L.INI_OPER,
  L.FIM_OPER,
  O.INI_PAUSA,
  O.FIM_PAUSA,
  M.DESCRICAO AS MOTIV_PAUSAS,
  O.DATA AS DATA_PAUSAS,
  L.DATA AS DATA_INI_OPER
FROM
  VROPERAD V
  LEFT OUTER JOIN OPEPAUSA O ON (O.OPERADOR = V.CODIGO)
  FULL OUTER JOIN LIG_CAB L ON (L.DATA = O.DATA)
  AND (L.OPERADOR = V.CODIGO)
  LEFT OUTER JOIN MPAUSA M ON (M.CODIGO = O.MOTIVO)
WHERE
  L.DATA BETWEEN '08/06/2010' AND '08/10/2010'
ORDER BY
  L.DATA,
  V.NOME
Responder

10/08/2010

Emerson Nascimento

SELECT
  V.CODIGO,
  V.NOME,
  L.INI_OPER,
  L.FIM_OPER,
  O.INI_PAUSA,
  O.FIM_PAUSA,
  M.DESCRICAO AS MOTIV_PAUSAS,
  O.DATA AS DATA_PAUSAS,
  L.DATA AS DATA_INI_OPER
FROM
  LIG_CAB L
INNER JOIN
  VROPERAD V ON (V.CODIGO = L.OPERADOR)
LEFT JOIN
  OPEPAUSA O ON (O.OPERADOR = L.OPERADOR and O.DATA = L.DATA)
LEFT JOIN
  MPAUSA M ON (M.CODIGO = O.MOTIVO)
WHERE
  L.DATA BETWEEN '07/28/2010' AND '08/02/2010'
ORDER BY
  L.DATA
Responder

10/08/2010

Elton ésqui

É quase isso!
Esse exclui o que não tem pausa...mas eu preciso exibir pelo menos se iniciou a operação!
Responder

10/08/2010

Elton ésqui

Perdoe-me Emerson.
Dessa maneira funcionou sim!!! Ótimo!

Muitíssimo obrigado!

Elton

PS: Responda para eu fechar o tópico com feedback.
Valeu

Responder

10/08/2010

Emerson Nascimento

SELECT
  V.CODIGO,
  V.NOME,
  L.INI_OPER,
  L.FIM_OPER,
  O.INI_PAUSA,
  O.FIM_PAUSA,
  M.DESCRICAO AS MOTIV_PAUSAS,
  O.DATA AS DATA_PAUSAS,
  L.DATA AS DATA_INI_OPER
FROM
  LIG_CAB L
INNER JOIN
  VROPERAD V ON (V.CODIGO = L.OPERADOR)
LEFT JOIN
  OPEPAUSA O ON (O.OPERADOR = L.OPERADOR and O.DATA = L.DATA)
LEFT JOIN
  MPAUSA M ON (M.CODIGO = O.MOTIVO)
WHERE
  L.DATA BETWEEN '07/28/2010' AND '08/02/2010'
ORDER BY
  L.DATA


eu estava achando estranho não funcionar dessa maneira. o importante é que o problema foi resolvido.

Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar