Select para retornar somente uma linha

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
VinicerasMG
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Seg, 14 Mai 2007 10:15 am
Localização: Coronel Fabriciano - MG
Vinícius de Araújo Lopes
PID - Gerência de Desenvolvimento de Sistemas
Analista de Sistemas
š valopes@usiminas.com.br

Saudações a todos.

Estou com uma dúvida aqui meio cabeluda e preciso de uma ajudinha. Tenho uma tabela (TB_RESULTADO_INDICADOR) contendo os seguintes campos:
cd_centro (codigo da empresa)
cd_indicador_performance (código da linha de produção)
cd_periodo (1 para dia, 2 para mês e 3 para ano)
tp_dado (real ou meta ou meta acumulada ou real acumulado)
dt_resultado (data do resultado)
vl_indicador (resultado em si, valor numérico)

Preciso a apresentar os dados de produção de um processo produtivo em um relatório (Crystal Reports) da seguinte forma:

| Dia | mês |Plano |
|cd_indicador|Meta|Real|Var|IC%|Meta|Real|Var|IC%|Mensal|

onde os parâmetro de consulta são o código da empresa e a data. IC% é o índice de consecução. Para uma determinada data,
são apresentadas a meta do dia, o valor real produzido, a variação (real-meta) e o IC, bem como (apartir do dia 1º do mês)
a meta acumulada até o dia, a produção real até o dia e o IC. Por último é apresentado o plano para o mês.

O select utilizado (que retorna somente uma linha), é o seguinte:

Selecionar tudo

SELECT A.CD_INDICADOR_PERFORMANCE, A.VL_INDICADOR AS META, B.VL_INDICADOR AS REAL, 
       (B.VL_INDICADOR  - A.VL_INDICADOR) AS VARDIA, 
       ROUND(DECODE(NVL(A.VL_INDICADOR, 0), 0, 0, NVL(B.VL_INDICADOR, 0)/A.VL_INDICADOR * 100), 1) AS ICDIA,
       C.VL_INDICADOR AS ACUMMETA, D.VL_INDICADOR AS ACUMREAL, 
       (D.VL_INDICADOR  - C.VL_INDICADOR) AS VARACUM, 
       ROUND(DECODE(NVL(C.VL_INDICADOR, 0), 0, 0, NVL(D.VL_INDICADOR, 0)/C.VL_INDICADOR * 100), 1) AS ICACUM,
       E.VL_INDICADOR AS PLANO
FROM   TB_RESULTADO_INDICADOR A, TB_RESULTADO_INDICADOR B, TB_RESULTADO_INDICADOR C, TB_RESULTADO_INDICADOR D, TB_RESULTADO_INDICADOR E
WHERE  A.CD_CENTRO    = {?empresa_filtro}
AND    A.CD_INDICADOR_PERFORMANCE = 552
AND    A.CD_PERIODO   = 1
AND    A.TP_DADO      = 'META'
AND    A.DT_RESULTADO = {?data}
AND    B.CD_CENTRO    = {?empresa_filtro}
AND    B.CD_INDICADOR_PERFORMANCE = 552
AND    B.CD_PERIODO   = 1
AND    B.TP_DADO      = 'REAL'
AND    B.DT_RESULTADO = {?data}
AND    C.CD_CENTRO    = {?empresa_filtro}
AND    C.CD_INDICADOR_PERFORMANCE = 552
AND    C.CD_PERIODO   = 2
AND    C.TP_DADO      = 'ACUM META'
AND    C.DT_RESULTADO = {?data}
AND    D.CD_CENTRO    = {?empresa_filtro}
AND    D.CD_INDICADOR_PERFORMANCE = 552
AND    D.CD_PERIODO   = 2
AND    D.TP_DADO      = 'ACUM REAL'
AND    D.DT_RESULTADO = {?data}
AND    E.CD_CENTRO    = {?empresa_filtro}
AND    E.CD_INDICADOR_PERFORMANCE = 552
AND    E.CD_PERIODO   = 2
AND    E.TP_DADO      = 'META'
AND    E.DT_RESULTADO = LAST_DAY({?data})
O problema acontece quando não existe um dos dados. Quando, por exemplo, não existe a meta para o dia, toda a linha
aparece em branco, mesmo existindo o valor real produzido. O que fazer para que que os valores existentes na tabela
sejam disponibilizados, mesmo quando falte algum dado??

Não sei se fui suficientemente claro na explicação do problema, mas desde já, agradeço a atenção.[/img]
Imagem
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

Seria mais ou menos isso, brother?

Caso ele não passe essa data abaixo:

Selecionar tudo

 AND E.DT_RESULTADO = LAST_DAY({?data}) 
Traga todos os registros?

Selecionar tudo

  AND E.DT_RESULTADO = NVL ( LAST_DAY({?data}), E.DT_RESULTADO ) 
Não sei se entendi direito, caso não seja isso, manda novamente, ok?
VinicerasMG
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Seg, 14 Mai 2007 10:15 am
Localização: Coronel Fabriciano - MG
Vinícius de Araújo Lopes
PID - Gerência de Desenvolvimento de Sistemas
Analista de Sistemas
š valopes@usiminas.com.br

Na verdade não é isso trevisolli.
Os parâmetros data e empresa_filtro sempre serão fornecidos (e os mesmos em todos os lugares que forem necessários...por exemplo, sempre a mesma data onde aparece o parâmetro {?data}). Aconte é que quando não há algum dos valores na tabela (real do dia, meta do dia, meta acumulada.... ) a linha inteira fica em branco.

No caso de

Selecionar tudo

AND E.DT_RESULTADO = LAST_DAY({?data})
serve para selecionar o plano do mês (plano no último dia do mês). {?data} e {?empresa_filtro} serão sempre fornecidos.

Obrigado
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

Bom, brother, pelo que entendi, você tem uma saída:

Você pode tratar um when_no_data_found nesta query.

Por exemplo, se o trecho abaixo não retornar nada:

Selecionar tudo

AND    E.CD_CENTRO    = {?empresa_filtro} 
AND    E.CD_INDICADOR_PERFORMANCE = 552 
AND    E.CD_PERIODO   = 2 
AND    E.TP_DADO      = 'META' 
AND    E.DT_RESULTADO = LAST_DAY({?data})
Você pode no when_no_data_found, fazer a querie novamente (sem este trecho) e, assim por diante, no when_no_data_found deste, fazer com os demais.

qualquer coisa manda ai.
Avatar do usuário
TBou
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 136
Registrado em: Qui, 05 Ago 2004 9:33 am
Localização: Campo Grande - MS
Thiago Bourscheidt
thiago.info@apoiorural.com.br
Analista de Sistemas

Bom Dia Senhores..

Fiz umas piras nesta select....
eu acho que deve dar certo

utilizei junção externa e NVL para o caso da tabela A não ter registros correspondentes, coloquei o comentario na select explicando.

veja os codigos abaixo:

Selecionar tudo

SELECT A.CD_INDICADOR_PERFORMANCE, A.VL_INDICADOR AS META, B.VL_INDICADOR AS REAL,
       (B.VL_INDICADOR  - A.VL_INDICADOR) AS VARDIA,
       ROUND(DECODE(NVL(A.VL_INDICADOR, 0), 0, 0, NVL(B.VL_INDICADOR, 0)/A.VL_INDICADOR * 100), 1) AS ICDIA,
       C.VL_INDICADOR AS ACUMMETA, D.VL_INDICADOR AS ACUMREAL,
       (D.VL_INDICADOR  - C.VL_INDICADOR) AS VARACUM,
       ROUND(DECODE(NVL(C.VL_INDICADOR, 0), 0, 0, NVL(D.VL_INDICADOR, 0)/C.VL_INDICADOR * 100), 1) AS ICACUM,
       E.VL_INDICADOR AS PLANO
FROM   TB_RESULTADO_INDICADOR A, TB_RESULTADO_INDICADOR B, TB_RESULTADO_INDICADOR C, TB_RESULTADO_INDICADOR D, TB_RESULTADO_INDICADOR E
WHERE  C.CD_CENTRO    = B.CENTRO
AND    C.CD_INDICADOR_PERFORMANCE = B.CD_INDICADOR_PERFORMANCE
AND    C.CD_PERIODO   = 2
AND    C.TP_DADO      = 'ACUM META'
AND    C.DT_RESULTADO = B.DT_RESULTADO
AND    D.CD_CENTRO    = B.CENTRO
AND    D.CD_INDICADOR_PERFORMANCE = B.CD_INDICADOR_PERFORMANCE
AND    D.CD_PERIODO   = 2
AND    D.TP_DADO      = 'ACUM REAL'
AND    D.DT_RESULTADO = B.DT_RESULTADO
AND    E.CD_CENTRO    = B.CONTRO
AND    E.CD_INDICADOR_PERFORMANCE = B.CD_INDICADOR_PERFORMANCE
AND    E.CD_PERIODO   = 2
AND    E.TP_DADO      = 'META'
AND    E.DT_RESULTADO = LAST_DAY(B.DT_RESULTADO)
/* SEGUNDO   -- ADICIONEI JUNCAO EXTERNA NOS RELACIONAMENTOS DA TABELA 'A' COM A TABELA 'B' */
/*           -- COLOQUEI NVL PARA A SELECT TRAZER AS OUTRAS INFORMAÇÕES
/*              MESMO QUE NÃO TENHA REGISTROS DO RELACIONAMENTO AxB */
AND    A.CD_CENTRO                = (+) B.CENTRO
AND    A.CD_INDICADOR_PERFORMANCE = (+) B.CD_INDICADOR_PERFORMANCE
AND    A.DT_RESULTADO             = (+) B.DT_RESULTADO
AND    NVL(A.CD_PERIODO,1)        = 1
AND    NVL(A.TP_DADO,'META')      = 'META'
/* PRIMEIRO  -- EU RELACIONEI AS TABELAS COM A TABELA 'B' E USEI OS FILTROS COMUNS UMA VEZ APENAS*/
/*           -- COLOQUEI OS FILTROS APENAS NA TABELA 'B' E COLOOQUEI EM BAIXO PARA FILTRAR PRIMEIRO. */
/*           -- ISSO SO PARA MELHORAR A ESTRUTURA DA SELECT...não INFLUI NO RESULTADO */
AND    B.CD_CENTRO    = {?empresa_filtro}
AND    B.CD_INDICADOR_PERFORMANCE = 552
AND    B.CD_PERIODO   = 1
AND    B.TP_DADO      = 'REAL'
AND    B.DT_RESULTADO = {?data}

espero que de certo...até mais
Avatar do usuário
TBou
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 136
Registrado em: Qui, 05 Ago 2004 9:33 am
Localização: Campo Grande - MS
Thiago Bourscheidt
thiago.info@apoiorural.com.br
Analista de Sistemas

OPas....Desculpe inverti a junção externa....sempre acabo confundindo.

fix um teste aqui e você precisa mudar a junção

Selecionar tudo

AND    A.CD_CENTRO                (+) = B.CENTRO
AND    A.CD_INDICADOR_PERFORMANCE (+) = B.CD_INDICADOR_PERFORMANCE
AND    A.DT_RESULTADO             (+) = B.DT_RESULTADO
o codigo (+) deve ficar no lado da tabela que não vai trazer os registros.
VinicerasMG
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Seg, 14 Mai 2007 10:15 am
Localização: Coronel Fabriciano - MG
Vinícius de Araújo Lopes
PID - Gerência de Desenvolvimento de Sistemas
Analista de Sistemas
š valopes@usiminas.com.br

Ola TBou

Agradeço por seu post.
Fiz um teste aqui e continua não retornando nada. Na tabela só existem os registros de REAL do dia e REAL Acum.

Eu na verdade desisti deste select e fiz o relatório de outra forma. Desisti da idéia de trazer somente uma linha e ter que montar o relatório "no braço". Refiz o select trazendo os valores dos indicadores filtrando por departamento. Ficou bem melhor pra dar manutenção no relatório.

A solução para o problema foi o casamento dos parâmetros da tabela tb_resultado_indicador com uma outra que chama tb_visao_sistema adicionando o (+) em todas as junções.

Obrigado a todos que responderam e um abraço
Responder
  • Informação
  • Quem está online

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