Página 1 de 1

Select para retornar somente uma linha

Enviado: Seg, 14 Mai 2007 11:08 am
por VinicerasMG
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

Enviado: Seg, 14 Mai 2007 11:32 am
por Trevisolli
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?

Enviado: Seg, 14 Mai 2007 1:17 pm
por VinicerasMG
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

Enviado: Seg, 14 Mai 2007 6:50 pm
por Trevisolli
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.

Enviado: Qui, 17 Mai 2007 11:37 am
por TBou
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

Enviado: Qui, 17 Mai 2007 11:43 am
por TBou
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.

Enviado: Qui, 17 Mai 2007 4:17 pm
por VinicerasMG
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