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
  

Mensagemem Seg, 14 Mai 2007 11:08 am

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:
Código: Selecionar todos
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
VinicerasMG
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

Mensagemem Seg, 14 Mai 2007 11:32 am

Seria mais ou menos isso, brother?

Caso ele não passe essa data abaixo:
Código: Selecionar todos
AND E.DT_RESULTADO = LAST_DAY({?data})


Traga todos os registros?

Código: Selecionar todos
  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?
Trevisolli
Localização: Araraquara - SP

Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Mensagemem Seg, 14 Mai 2007 1:17 pm

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

Mensagemem Seg, 14 Mai 2007 6:50 pm

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:

Código: Selecionar todos
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.
Trevisolli
Localização: Araraquara - SP

Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Mensagemem Qui, 17 Mai 2007 11:37 am

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:

Código: Selecionar todos
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
TBou
Localização: Campo Grande - MS

Thiago Bourscheidt
thiago.info@apoiorural.com.br
Analista de Sistemas

Mensagemem Qui, 17 Mai 2007 11:43 am

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

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


Código: Selecionar todos
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.
TBou
Localização: Campo Grande - MS

Thiago Bourscheidt
thiago.info@apoiorural.com.br
Analista de Sistemas

Mensagemem Qui, 17 Mai 2007 4:17 pm

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


  • Veja também
    Respostas
    ExibiÇões
    Última mensagem


    Voltar para SQL

    Quem está online

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