Page tree
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Current »

Produto: maxInsights



1.0 Exemplos de SQL maxInsights

Este documento apresenta consultas SQL voltadas para geração de informações estratégicas, com foco em apoiar análises e decisões de negócio para clientes que utilizam o maxInsights.

1.1 Informações de atendimento

Visitas X Atendimentos

Relacionamento entre fato_atendimento e fato_visitas_realizadas

SELECT fa.sequencia_realizada_cliente as sequencia_realizada,

       fa.codigo_vendedor,

       fa.data_atendimento,

       fa.horainicio_atendimento AS inicio,

       fa.horafim_atendimento AS fim,

       fa.tempo_atendimento,

       fa.tempo_deslocamento,

       fa.codigo_cliente,

       fa.numero_pedido,

       fvr.id_rota,

       CASE WHEN dmj.id IS NULL THEN '' ELSE dmj.id || ' - ' || dmj.descricao END AS motivo,

       fvr.observacao,

       CASE WHEN fvr.id_rota IS NULL OR fvr.id_rota = '0' THEN 'N' ELSE 'S' END AS agendado,

       fvr.pdv

FROM fato_atendimento fa 

INNER JOIN fato_visitas_realizadas fvr 

        ON fvr."data" = fa.data_atendimento

       AND fvr.codigo_vendedor = fa.codigo_vendedor 

       AND coalesce(fa.numero_pedido,0) = coalesce(fvr.numero_pedido,0)

       AND coalesce(fa.codigo_justificativa,'0') = coalesce(fvr.codigo_justificativa,'0')

 LEFT JOIN dim_motivo_justificativa dmj ON dmj.id            = fvr.motivo

WHERE fa.codigo_vendedor = '10' --CODIGO do VENDEDOR (RCA)

  AND fa.data_atendimento = DATE '2025-10-7' --DATA DO ATENDIMENTO

ORDER BY data_atendimento, codigo_vendedor, sequencia_realizada


1.2 Agendamentos e visitas

Dados detalhados com:

  • Ordem de agendamento de visitas
  • Ordem de execução das visitas
  • Visitas avulsas (não agendadas)

WITH params AS (

    SELECT DATE '2025-10-28'      AS data_, --DATA DA VISITA

           CAST('999' AS TEXT) AS codigo_vendedor_ --CODIGO DO VENDEDOR

  ),


  /* ===================== [A] Recortes base ===================== */

  fvr_cut AS (  -- visitas realizadas (já tipado)

    SELECT

      data::date                              AS data,

      hora                                    AS hora_raw,

      codigo_cliente,

      CAST(REPLACE(id_rota, '.0', '') AS INT) AS id_rota,

      sequencia_realizada                     AS sequencia_realizada_original,

      codigo_vendedor,

      motivo,

      pdv,

      numero_pedido,

      codigo_justificativa,

      observacao

    FROM fato_visitas_realizadas

    CROSS JOIN params 

    WHERE codigo_vendedor = params.codigo_vendedor_ 

      AND data::date = params.data_ 

      AND COALESCE(motivo, 0) <> 999

  ),


  fpv_cut AS (  -- planejamento (já tipado)

    SELECT

      data::date      AS data,

      '23:59:59'      AS hora_pln_raw,

      codigo_cliente,

      CAST(id_rota AS INT) AS id_rota,

      sequencia,

      codigo_vendedor

    FROM fato_planejamento_visitas

    CROSS JOIN params 

    WHERE codigo_vendedor = params.codigo_vendedor_ 

      AND data::date = params.data_ 

  ),


  /* ===================== [C] Visitas + join com fato_atendimento ===================== */

  visitas AS (

    SELECT

      fvr.data,

      fvr.codigo_cliente,

      CAST(fvr.id_rota AS VARCHAR)                        AS id_rota,

      TRY_CAST(fpv.sequencia AS INTEGER)                  AS sequencia_planejada,   -- força tipo

      TRY_CAST(fa.sequencia_realizada_cliente AS INTEGER) AS sequencia_realizada,   -- força tipo

      fvr.codigo_vendedor,

      CASE WHEN dmj.id IS NULL THEN '' ELSE dmj.descricao END AS motivo,

      fvr.pdv,

      fvr.numero_pedido,

      fvr.codigo_justificativa,

      fvr.observacao,

      fa.tempo_atendimento,

      fa.tempo_deslocamento

    FROM fato_atendimento fa 

    INNER JOIN fvr_cut fvr 

      ON fvr.data = fa.data_atendimento

     AND fvr.codigo_vendedor = fa.codigo_vendedor

     /* match por pedido/justificativa (exclusivo) */

     AND coalesce(fa.numero_pedido,0) = coalesce(fvr.numero_pedido,0)

     AND coalesce(fa.codigo_justificativa,'0') = coalesce(fvr.codigo_justificativa,'0')

    LEFT JOIN fpv_cut fpv

      ON fpv.data            = fvr.data

     AND fpv.id_rota         = fvr.id_rota

     AND fpv.codigo_vendedor = fvr.codigo_vendedor

     AND fpv.codigo_cliente  = fvr.codigo_cliente

     AND fpv.id_rota IS NOT NULL

     AND fpv.id_rota <> 0

    LEFT JOIN dim_motivo_justificativa dmj 

      ON dmj.id = fvr.motivo

  ),


  /* ===================== [E] SELECT final: bloco visitas ===================== */

  bloco_visitas AS (

    SELECT DISTINCT

      /* garanta tipos inteiros aqui também */

      TRY_CAST(v.sequencia_planejada AS INTEGER) AS sequencia_planejada,

      TRY_CAST(v.sequencia_realizada AS INTEGER) AS sequencia_realizada,

      v.data,

      v.codigo_cliente,

      v.id_rota,

      v.codigo_vendedor,

      v.motivo,

      v.observacao,

      CASE WHEN v.id_rota IS NULL OR v.id_rota = '0' THEN 'N' ELSE 'S' END AS agendado,

      v.pdv,

      v.tempo_atendimento,

      v.tempo_deslocamento,

      v.numero_pedido

    FROM visitas v

  ),


  /* ===================== [E2] Planejado que não virou visita (ANTI-JOIN) ===================== */

  planejado_base AS (

    SELECT 

      TRY_CAST(fpv.sequencia AS INTEGER)       AS sequencia_planejada,  -- inteiro

      CAST(0 AS INTEGER)                       AS sequencia_realizada,  -- inteiro (zero)

      fpv.data                                 AS data,

      fpv.codigo_cliente,

      CAST(fpv.id_rota AS VARCHAR)             AS id_rota,

      fpv.codigo_vendedor,

      ''                                       AS motivo,

      ''                                       AS observacao,

      CASE WHEN fpv.id_rota IS NULL OR fpv.id_rota = 0 THEN 'N' ELSE 'S' END AS agendado,

      ''                                       AS pdv,

      '00:00:00'                               AS tempo_atendimento,

      '00:00:00'                               AS tempo_deslocamento,

      0                                        as numero_pedido

    FROM fpv_cut fpv

  ),

  exec_keys AS (

    SELECT DISTINCT data, codigo_vendedor, codigo_cliente, id_rota

    FROM fvr_cut

  ),

  bloco_planejado_nao_exec AS (

    SELECT pb.*

    FROM planejado_base pb

    LEFT JOIN exec_keys k

      ON  k.data             = pb.data

      AND k.codigo_vendedor  = pb.codigo_vendedor

      AND k.codigo_cliente   = pb.codigo_cliente

      AND CAST(k.id_rota AS VARCHAR) = pb.id_rota

    WHERE k.data IS NULL

  )


  /* ===================== [F] Resultado unificado (com tipos alinhados) ===================== */

  SELECT *

  FROM bloco_visitas

  UNION ALL

  SELECT *

  FROM bloco_planejado_nao_exec

ORDER BY data, codigo_vendedor, sequencia_realizada




1.3 Indicadores de agendamentos e visitas


Cálculo dos indicadores:

  • total_planejadas - total de visitas planejada
  • total_visitas_realizadas - total de visitas realizadas
  • visitas_realizadas_das_planejadas - quantas visitas planejadas foram realizadas
  • total_visitas_nao_realizadas - quantas visitas planejadas não foram realizadas
  • cumprimento_agenda_visitas - percentual de visitas planejadas realizadas
  • tempo_medio_visita - tempo médio de duração das visitas
  • tempo_medio_deslocamento - tempo médio de deslocamento/percurso
  • visitas_convertidas - total de visitas convertidas em pedidos / positivas
  • taxa_conversao - percentual de conversão / positivação
  • visitas_avulsas - total de visitas avulsas / não planejadas
  • top_10_motivos - 10 motivos de não compra mais frequentes


WITH totalizador AS (

  WITH params AS (

    SELECT DATE '2025-10-28'      AS data_, --DATA DA VISITA

           CAST('999' AS TEXT) AS codigo_vendedor_ --CODIGO DO VENDEDOR


  ),

  /* ===================== [A] Recortes base ===================== */

  fvr_cut AS (  -- visitas realizadas (já tipado)

    SELECT

      data::date                              AS data,

      hora                                    AS hora_raw,

      codigo_cliente,

      CAST(REPLACE(id_rota, '.0', '') AS INT) AS id_rota,

      sequencia_realizada                     AS sequencia_realizada_original,

      codigo_vendedor,

      motivo,

      pdv,

      numero_pedido,

      codigo_justificativa,

      observacao

    FROM fato_visitas_realizadas

    CROSS JOIN params

    WHERE codigo_vendedor = params.codigo_vendedor_

      AND data::date = params.data_

      AND COALESCE(motivo, 0) <> 999

  ),

  fpv_cut AS (  -- planejamento (já tipado)

    SELECT

      data::date      AS data,

      '23:59:59'      AS hora_pln_raw,

      codigo_cliente,

      CAST(id_rota AS INT) AS id_rota,

      sequencia,

      codigo_vendedor

    FROM fato_planejamento_visitas

    CROSS JOIN params

    WHERE codigo_vendedor = params.codigo_vendedor_

      AND data::date = params.data_

  ),

  /* ===================== [C] Visitas + join com fato_atendimento ===================== */

  visitas AS (

    SELECT

      fvr.data,

      fvr.codigo_cliente,

      CAST(fvr.id_rota AS VARCHAR)                        AS id_rota,

      TRY_CAST(fpv.sequencia AS INTEGER)                  AS sequencia_planejada,   -- força tipo

      TRY_CAST(fa.sequencia_realizada_cliente AS INTEGER) AS sequencia_realizada,   -- força tipo

      fvr.codigo_vendedor,

      CASE WHEN dmj.id IS NULL THEN '' ELSE dmj.descricao END AS motivo,

      fvr.pdv,

      fvr.numero_pedido,

      fvr.codigo_justificativa,

      fvr.observacao,

      fa.tempo_atendimento,

      fa.tempo_deslocamento

    FROM fato_atendimento fa

    INNER JOIN fvr_cut fvr

      ON fvr.data = fa.data_atendimento

     AND fvr.codigo_vendedor = fa.codigo_vendedor

     /* match por pedido/justificativa (exclusivo) */

     AND coalesce(fa.numero_pedido,0) = coalesce(fvr.numero_pedido,0) 

     AND coalesce(fa.codigo_justificativa,'0') = coalesce(fvr.codigo_justificativa,'0')

    LEFT JOIN fpv_cut fpv

      ON fpv.data            = fvr.data

     AND fpv.id_rota         = fvr.id_rota

     AND fpv.codigo_vendedor = fvr.codigo_vendedor

     AND fpv.codigo_cliente  = fvr.codigo_cliente

     AND fpv.id_rota IS NOT NULL

     AND fpv.id_rota <> 0

    LEFT JOIN dim_motivo_justificativa dmj

      ON dmj.id = fvr.motivo

  ),

  /* ===================== [E] SELECT final: bloco visitas ===================== */

  bloco_visitas AS (

    SELECT DISTINCT

      /* garanta tipos inteiros aqui também */

      TRY_CAST(v.sequencia_planejada AS INTEGER) AS sequencia_planejada,

      TRY_CAST(v.sequencia_realizada AS INTEGER) AS sequencia_realizada,

      v.data,

      v.codigo_cliente,

      v.id_rota,

      v.codigo_vendedor,

      v.motivo,

      v.observacao,

      CASE WHEN v.id_rota IS NULL OR v.id_rota = '0' THEN 'N' ELSE 'S' END AS agendado,

      v.pdv,

      v.tempo_atendimento,

      v.tempo_deslocamento,

      v.numero_pedido

    FROM visitas v

  ),

  /* ===================== [E2] Planejado que não virou visita (ANTI-JOIN) ===================== */

  planejado_base AS (

    SELECT

      TRY_CAST(fpv.sequencia AS INTEGER)       AS sequencia_planejada,  -- inteiro

      CAST(0 AS INTEGER)                       AS sequencia_realizada,  -- inteiro (zero)

      fpv.data                                 AS data,

      fpv.codigo_cliente,

      CAST(fpv.id_rota AS VARCHAR)             AS id_rota,

      fpv.codigo_vendedor,

      ''                                       AS motivo,

      ''                                       AS observacao,

      CASE WHEN fpv.id_rota IS NULL OR fpv.id_rota = 0 THEN 'N' ELSE 'S' END AS agendado,

      ''                                       AS pdv,

      '00:00:00'                               AS tempo_atendimento,

      '00:00:00'                               AS tempo_deslocamento,

      0                                        as numero_pedido

    FROM fpv_cut fpv

  ),

  exec_keys AS (

    SELECT DISTINCT data, codigo_vendedor, codigo_cliente, id_rota

    FROM fvr_cut

  ),

  bloco_planejado_nao_exec AS (

    SELECT pb.*

    FROM planejado_base pb

    LEFT JOIN exec_keys k

      ON  k.data             = pb.data

      AND k.codigo_vendedor  = pb.codigo_vendedor

      AND k.codigo_cliente   = pb.codigo_cliente

      AND CAST(k.id_rota AS VARCHAR) = pb.id_rota

    WHERE k.data IS NULL

  )

  /* ===================== [F] Resultado unificado (com tipos alinhados) ===================== */

  SELECT *

  FROM bloco_visitas

  UNION ALL

  SELECT *

  FROM bloco_planejado_nao_exec

),

-- ---------- util: transforma HH:MM:SS em segundos ----------

base AS (

  SELECT

    t.*,

    CASE

      WHEN NULLIF(t.tempo_atendimento,'') IS NULL THEN NULL

      ELSE (CAST(SPLIT_PART(t.tempo_atendimento, ':', 1) AS INT) * 3600)

         + (CAST(SPLIT_PART(t.tempo_atendimento, ':', 2) AS INT) * 60)

         +  CAST(SPLIT_PART(t.tempo_atendimento, ':', 3) AS INT)

    END AS tempo_atend_s,

    CASE

      WHEN NULLIF(t.tempo_deslocamento,'') IS NULL THEN NULL

      ELSE (CAST(SPLIT_PART(t.tempo_deslocamento, ':', 1) AS INT) * 3600)

         + (CAST(SPLIT_PART(t.tempo_deslocamento, ':', 2) AS INT) * 60)

         +  CAST(SPLIT_PART(t.tempo_deslocamento, ':', 3) AS INT)

    END AS tempo_desl_s

  FROM totalizador t

),

-- ---------- agregados principais (sem COUNT_IF) ----------

aggs AS (

  SELECT

    COUNT(distinct sequencia_planejada)                                        AS visitas_planejadas,

    COUNT(distinct sequencia_realizada)                                        AS visitas_realizadas_total,

    COUNT(distinct CASE WHEN agendado = 'S'

                         AND COALESCE(sequencia_realizada,0) > 0

             THEN sequencia_planejada ELSE null END)                           AS visitas_realizadas_das_planejadas,

    COUNT(distinct CASE WHEN agendado = 'S'

              AND COALESCE(sequencia_realizada,0) = 0

             THEN sequencia_planejada ELSE null END)                           AS visitas_nao_realizadas, --buscar cenário com planejadas não executadas

    AVG(NULLIF(tempo_atend_s, 0))                                              AS avg_visita_s,

    AVG(NULLIF(tempo_desl_s,  0))                                              AS avg_desloc_s,

    SUM(CASE WHEN COALESCE(sequencia_realizada,0) > 0

                 AND COALESCE(numero_pedido,0) > 0 THEN 1 ELSE 0 END)          AS visitas_convertidas,

    COUNT(case when cast(sequencia_planejada as integer) is null

                and cast(sequencia_realizada as integer) is not null

               then sequencia_realizada else NULL end)                         AS visitas_avulsas

  FROM base

),

-- ---------- KPIs já formatados ----------

kpis AS (

  SELECT

    visitas_planejadas,

    visitas_realizadas_total,

    visitas_realizadas_das_planejadas,

    visitas_nao_realizadas,

    visitas_convertidas,

    visitas_avulsas,

    CASE

      WHEN visitas_planejadas = 0 THEN 0.0

      ELSE ROUND((visitas_realizadas_das_planejadas::DECIMAL(18,6)

                 / NULLIF(visitas_planejadas,0)) * 100, 2)

    END AS cumprimento_agenda_pct,

    CASE

      WHEN avg_visita_s IS NULL THEN '00:00:00'

      ELSE

        LPAD(CAST(FLOOR(avg_visita_s/3600) AS INT)::VARCHAR, 2, '0') || ':' ||

        LPAD(CAST(FLOOR(MOD(avg_visita_s,3600)/60) AS INT)::VARCHAR, 2, '0') || ':' ||

        LPAD(CAST(FLOOR(MOD(avg_visita_s,60)) AS INT)::VARCHAR, 2, '0')

    END AS tempo_medio_visita,

    CASE

      WHEN avg_desloc_s IS NULL THEN '00:00:00'

      ELSE

        LPAD(CAST(FLOOR(avg_desloc_s/3600) AS INT)::VARCHAR, 2, '0') || ':' ||

        LPAD(CAST(FLOOR(MOD(avg_desloc_s,3600)/60) AS INT)::VARCHAR, 2, '0') || ':' ||

        LPAD(CAST(FLOOR(MOD(avg_desloc_s,60)) AS INT)::VARCHAR, 2, '0')

    END AS tempo_medio_deslocamento,

    CASE

      WHEN visitas_realizadas_total = 0 THEN 0.0

      ELSE ROUND((visitas_convertidas::DECIMAL(18,6)

                 / NULLIF(visitas_realizadas_total,0)) * 100, 2)

    END AS taxa_conversao_pct

  FROM aggs

),

-- ---------- principais justificativas de não venda ----------

justificativas AS (

  SELECT

    LISTAGG(CASE WHEN NULLIF(TRIM(motivo),'') IS NULL THEN '[sem motivo]' ELSE TRIM(motivo) END, ', ') WITHIN GROUP (ORDER BY CASE WHEN NULLIF(TRIM(motivo),'') IS NULL THEN '[sem motivo]' ELSE TRIM(motivo) END) AS top_10_motivos,

    COUNT(*) AS qtde

  FROM base

  WHERE COALESCE(sequencia_realizada,0) > 0

    AND COALESCE(numero_pedido,0) = 0

  ORDER BY qtde DESC

  LIMIT 10

)

-- ==================== SAÍDA PRINCIPAL ====================

SELECT

  visitas_planejadas                             AS total_planejadas,

  visitas_realizadas_total                       AS total_visitas_realizadas,

  visitas_realizadas_das_planejadas,

  visitas_nao_realizadas                         AS total_visitas_nao_realizadas,

  cumprimento_agenda_pct                         AS cumprimento_agenda_visitas,

  tempo_medio_visita,

  tempo_medio_deslocamento,

  visitas_convertidas,

  taxa_conversao_pct                             AS taxa_conversao,

  visitas_avulsas,

  justificativas.top_10_motivos

FROM kpis

cross join justificativas



1.4 Painel de auditória - visitas


Relacionamento entre as tabelas fato_visitas_realizadas, fato_atendimento, fato_eventos e fato_pedido_realizado, listadas de forma semelhante ao painel de auditoria.


WITH params AS (

  SELECT DATE '2025-10-28'       AS data_, --DATA DA VISITA

         cast('999' AS TEXT)  AS codigo_vendedor_ --CODIGO DO VENDEDOR

),

/* ===================== [A] Recortes base ===================== */

fvr_cut AS (  -- visitas realizadas (já tipado)

  SELECT

    data::date                              AS data,

    hora                                    AS hora_raw,

    codigo_cliente,

    CAST(REPLACE(id_rota, '.0', '') AS int) AS id_rota,

    sequencia_realizada                     AS sequencia_realizada_original,

    codigo_vendedor,

    motivo,

    pdv,

    numero_pedido,

    codigo_justificativa,

    observacao

  FROM fato_visitas_realizadas

       CROSS JOIN params

  WHERE codigo_vendedor = params.codigo_vendedor_

    AND data::date = params.data_

    AND COALESCE(motivo, 0) <> 999

),

fpv_cut AS (  -- planejamento (já tipado)

  SELECT

    data::date      AS data,

    '23:59:59'      AS hora_pln_raw,

    codigo_cliente,

    CAST(id_rota AS int) AS id_rota,

    sequencia,

    codigo_vendedor

  FROM fato_planejamento_visitas

       CROSS JOIN params

  WHERE codigo_vendedor = params.codigo_vendedor_

    AND data::date = params.data_

),

/* ===================== [B] Hora do atendimento (fonte preferencial) ===================== */

hv AS (

  SELECT

    a.data_atendimento::date      AS data,

    a.codigo_vendedor             AS codigo_vendedor,

    a.codigo_cliente              AS codigo_cliente,

    a.horainicio_atendimento      AS hora_ini_raw,

    a.horafim_atendimento         AS hora_fim_raw,

    a.tempo_atendimento           AS tempo_atend_raw,

    a.numero_pedido               AS numero_pedido,

    a.codigo_justificativa        AS codigo_justificativa,

    a.sequencia_realizada_cliente AS sequencia_realizada,

    a.tempo_deslocamento

  FROM fato_atendimento a

       CROSS JOIN params  

  WHERE a.data_atendimento::date = params.data_

    AND a.codigo_vendedor = params.codigo_vendedor_

),

/* ===================== [C] Normalizadores de hora (robusto) ===================== */

visitas AS (

  SELECT

    fvr.data,

    REGEXP_REPLACE(COALESCE(hv.hora_ini_raw, fvr.hora_raw), '[^0-9]', '') AS h_ini_clean,

    REGEXP_REPLACE(hv.hora_fim_raw, '[^0-9]', '')                          AS h_fim_clean,

    fvr.hora_raw,

    hv.hora_ini_raw,

    hv.hora_fim_raw,

    hv.tempo_atend_raw,

    hv.tempo_deslocamento,

    fvr.codigo_cliente,

    CAST(fvr.id_rota AS varchar)        AS id_rota,

    fvr.sequencia_realizada_original,

    fpv.sequencia                       AS sequencia_planejada,

    hv.sequencia_realizada,

    fvr.codigo_vendedor,

    fvr.motivo,

    fvr.pdv,

    fvr.numero_pedido,

    fvr.codigo_justificativa,

    fvr.observacao

  FROM fvr_cut fvr

  LEFT JOIN fpv_cut fpv

         ON fpv.data            = fvr.data

        AND fpv.id_rota         = fvr.id_rota

        AND fpv.codigo_vendedor = fvr.codigo_vendedor

        AND fpv.codigo_cliente  = fvr.codigo_cliente

        AND fpv.id_rota IS NOT NULL

        AND fpv.id_rota <> 0

  LEFT JOIN hv

        ON hv.data            = fvr.data

       AND hv.codigo_vendedor = fvr.codigo_vendedor

       AND hv.codigo_cliente  = fvr.codigo_cliente

       AND coalesce(hv.numero_pedido, 0) = coalesce(fvr.numero_pedido, 0)

       AND coalesce(hv.codigo_justificativa, '0') = coalesce(fvr.codigo_justificativa, '0')

),

/* ===================== [D] Distância p/ PDV ===================== */

distancia_cliente AS (

  SELECT

    a.data_atendimento,

    a.codigo_cliente,

    a.codigo_vendedor,

    a.numero_pedido,

    a.codigo_justificativa,

    a.horainicio_atendimento      AS inicio_raw,

    a.horafim_atendimento         AS fim_raw,

    a.tempo_atendimento           AS atend_raw

  FROM fato_atendimento a

  INNER JOIN dim_cliente c

          ON c.codigo_cliente = a.codigo_cliente

  LEFT JOIN fato_eventos e

         ON CAST(e.data_hora_evento_tz AS date) = a.data_atendimento

        AND e.codigo_cliente = a.codigo_cliente

        AND e.codigo_usuario = a.codigo_usuario

  WHERE coalesce(e.justificativa_nao_venda_codigovinculacao, '0') = coalesce(a.codigo_justificativa, '0')

    AND coalesce(e.numero_pedido_rca, 0) = coalesce(a.numero_pedido, 0)

    AND e.tipo_evento IN ('PEDIDO','JUSTIFICATIVANAOVENDA')

),

/* ===================== [E] SELECT final: bloco visitas ===================== */

bloco_visitas AS (

  SELECT DISTINCT

    dv.codigo_filial,

    v.sequencia_planejada,

    v.sequencia_realizada,

    to_char(

      to_timestamp(NULLIF(LPAD(v.h_ini_clean, 6, '0'), ''), 'HH24MISS'),

      'HH24:MI:SS'

    ) AS inicio,

    to_char(

      to_timestamp(NULLIF(LPAD(v.h_fim_clean, 6, '0'), ''), 'HH24MISS'),

      'HH24:MI:SS'

    ) AS fim,

    v.tempo_atend_raw AS atend,

    v.tempo_deslocamento as percurso,

    fpr.numped,

    fpr.numpederp,

    v.data,

    v.codigo_cliente,

    dc.razaosocial AS nome_cliente,

    dc.latitude,

    dc.longitude,

    v.id_rota,

    v.codigo_vendedor,

    v.motivo AS motivo_id,

    CASE WHEN dmj.id IS NULL THEN '' ELSE dmj.id || ' - ' || dmj.descricao END AS motivo,

    CAST(fpr.vlpedido  AS NUMERIC(18, 2)) AS pedido,

    CAST(fpr.vlatend   AS NUMERIC(18, 2)) AS atendido,

    CAST(fpr.vlbonific AS NUMERIC(18, 2)) AS bonificacao,

    v.observacao AS observacao,

    CASE WHEN v.id_rota IS NULL OR v.id_rota = '0' THEN 'N' ELSE 'S' END AS agendado,

    v.pdv

  FROM visitas v

  LEFT JOIN dim_cliente              dc  ON dc.codigo_cliente = v.codigo_cliente

  LEFT JOIN dim_motivo_justificativa dmj ON dmj.id            = v.motivo

  LEFT JOIN fato_pedido_realizado    fpr

    ON fpr.data_completa   = v.data

   AND fpr.codigo_cliente  = v.codigo_cliente

   AND fpr.codigo_vendedor = v.codigo_vendedor

   AND fpr.numped          = v.numero_pedido

   AND v.motivo IS NULL

  LEFT JOIN dim_vendedores dv ON dv.codigo_vendedor = v.codigo_vendedor

  LEFT JOIN distancia_cliente dist

    ON dist.data_atendimento    = v.data

   AND dist.codigo_vendedor     = v.codigo_vendedor

   AND dist.codigo_cliente      = v.codigo_cliente

   AND dist.numero_pedido       = v.numero_pedido

   AND dist.codigo_justificativa= v.codigo_justificativa

),

/* ===================== [E2] Planejado que não virou visita (ANTI-JOIN) ===================== */

planejado_base AS (

  SELECT

    dv.codigo_filial,

    fpv.sequencia                         AS sequencia_planejada,

    0                                     AS sequencia_realizada,

    '00:00:00'                            AS inicio,

    '00:00:00'                            AS fim,

    '00:00:00'                            AS atend,

    '00:00:00'                            AS percurso,

    0                                     AS numped,

    0                                     AS numpederp,

    fpv.data                              AS data,

    fpv.codigo_cliente,

    dc.razaosocial                        AS nome_cliente,

    '0'                                   AS latitude,

    '0'                                   AS longitude,

    CAST(fpv.id_rota AS varchar)          AS id_rota,

    fpv.codigo_vendedor,

    0                                     AS motivo_id,

    ''                                    AS motivo,

    0.0                                   AS pedido,

    0.0                                   AS atendido,

    0.0                                   AS bonificacao,

    ''                                    AS observacao,

    CASE WHEN fpv.id_rota IS NULL OR fpv.id_rota = 0 THEN 'N' ELSE 'S' END AS agendado,

    ''                                    AS pdv

  FROM fpv_cut fpv

  LEFT JOIN dim_cliente    dc ON dc.codigo_cliente  = fpv.codigo_cliente

  LEFT JOIN dim_vendedores dv ON dv.codigo_vendedor = fpv.codigo_vendedor

),

exec_keys AS (

  SELECT DISTINCT data, codigo_vendedor, codigo_cliente, id_rota

  FROM fvr_cut

),

bloco_planejado_nao_exec AS (

  SELECT pb.*

  FROM planejado_base pb

  LEFT JOIN exec_keys k

    ON  k.data           = pb.data

    AND k.codigo_vendedor= pb.codigo_vendedor

    AND k.codigo_cliente = pb.codigo_cliente

    AND CAST(k.id_rota AS varchar) = pb.id_rota

  WHERE k.data IS NULL

)

/* ===================== [F] Resultado ===================== */

SELECT *

FROM bloco_visitas

UNION ALL

SELECT *

FROM bloco_planejado_nao_exec

ORDER BY

  codigo_vendedor,

  data,

  sequencia_realizada;


1.5 Painel de auditória - Pedidos, Justificativa de não venda e Venda avulsa


Classificar todas as visitas realizadas (pedidos ou justificativas) em três categorias:  'PEDIDO', 'JUSTIFICATIVANAOVENDA' ou 'VISITA AVULSA'. Utilizando apenas a fato_visitas_realizadas.




WITH ResultadosUnificados AS (

    SELECT

        v.data,

        v.hora,

        v.codigo_cliente,

        v.codigo_vendedor,

       

        -- Classifica o 'tipo_vinculo' com base na regra de negócio:

        CASE

            -- REGRA 1: Se o 'id_rota' é '0', significa que o cliente NÃO estava na agenda do vendedor. Portanto, é uma 'VISITA AVULSA'.

            WHEN v.id_rota = '0' THEN 'VISITA AVULSA'

           

            -- REGRA 2: Se o 'id_rota' NÃO é '0' (estava na agenda) E tem um número de pedido, é um 'PEDIDO'.

            WHEN v.numero_pedido IS NOT NULL THEN 'PEDIDO'


            -- REGRA 3: Se o 'id_rota' NÃO é '0' (estava na agenda) E tem um motivo (de não venda), é uma 'JUSTIFICATIVANAOVENDA'.

            WHEN v.motivo IS NOT NULL THEN 'JUSTIFICATIVANAOVENDA'

           

            -- Se não se encaixa em nada acima (ex: estava na agenda, mas não tem pedido nem motivo), trata como 'VISITA AVULSA'.

            ELSE 'VISITA AVULSA'

        END AS tipo_vinculo,

       

        v.observacao,

        v.numero_pedido,

        v.motivo,

        v.codigo_justificativa

    FROM

        -- Usamos a tabela 'fato_visitas_realizadas' como base.

        fato_visitas_realizadas AS v

)


-- Consulta final: Seleciona todos os dados da tabela

SELECT

    ru.data,

    ru.hora,

    ru.codigo_cliente,

    ru.codigo_vendedor,

    ru.tipo_vinculo,

    ru.observacao,

    ru.numero_pedido,

    ru.motivo,

    ru.codigo_justificativa

FROM

    ResultadosUnificados AS ru


1.6 Painel de auditória - Pedidos, Justificativa de não venda e Venda avulsa utilizando FATO_EVENTOS


Classificar todas as visitas realizadas (pedidos ou justificativas) em três categorias:  'PEDIDO', 'JUSTIFICATIVANAOVENDA' ou 'VISITA AVULSA'. Utilizando fato_visitas_realizadas e fato_eventos.


WITH VisitasComEventoBruto AS (

   

    -- Bloco 1: PEDIDOS (v.numero_pedido IS NOT NULL) Une a visita (v) com o evento bruto (e) que gerou o pedido

    SELECT

        v.data, v.hora, v.codigo_cliente, v.codigo_vendedor,

        v.id_rota, v.numero_pedido, v.motivo, v.codigo_justificativa,

        v.observacao,

        e.tipo_evento AS evento_bruto_encontrado -- Coluna de auditoria

    FROM

        fato_visitas_realizadas AS v

    LEFT JOIN

        fato_eventos AS e

        -- Condições do JOIN para PEDIDO:

        ON v.numero_pedido = e.numero_pedido_rca        -- Chave principal do pedido

        AND e.tipo_evento = 'PEDIDO'                    -- Garante que é o evento de Pedido

        AND v.data = CAST(e.data_hora_evento_tz AS DATE) -- Otimização do join

        AND v.codigo_vendedor = e.codigo_vendedor        -- Otimização do join

    WHERE

        v.numero_pedido IS NOT NULL -- Filtra apenas Pedidos da fato_visitas_realizadas

   

    UNION ALL

   

    -- Bloco 2: JUSTIFICATIVAS (v.numero_pedido IS NULL AND v.motivo IS NOT NULL) Une a visita (v) com o evento bruto (e) que gerou a justificativa

    SELECT

        v.data, v.hora, v.codigo_cliente, v.codigo_vendedor,

        v.id_rota, v.numero_pedido, v.motivo, v.codigo_justificativa,

        v.observacao,

        e.tipo_evento AS evento_bruto_encontrado -- Coluna de auditoria

    FROM

        fato_visitas_realizadas AS v

    LEFT JOIN

        fato_eventos AS e

        -- Condições do JOIN para JUSTIFICATIVA:

        ON v.codigo_justificativa = e.justificativa_nao_venda_codigovinculacao -- Chave da justificativa

        AND e.tipo_evento = 'JUSTIFICATIVANAOVENDA'      -- Garante que é o evento de Justificativa

        AND v.data = CAST(e.data_hora_evento_tz AS DATE) 

        AND v.codigo_vendedor = e.codigo_vendedor       

    WHERE

        v.numero_pedido IS NULL AND v.motivo IS NOT NULL -- Filtra apenas Justificativas


),


-- PASSO 2: Aplicar a classificação final (mesma lógica da consulta simples)

ResultadosUnificados AS (

    SELECT

        v.data,

        v.hora,

        v.codigo_cliente,

        v.codigo_vendedor,

       

        -- Classificação IDÊNTICA à consulta simples (baseada apenas em 'v')

        CASE

            -- REGRA 1: Se o 'id_rota' é '0', é 'VISITA AVULSA'.

            WHEN v.id_rota = '0' THEN 'VISITA AVULSA'

           

            -- REGRA 2: Se estava na agenda E tem pedido, é 'PEDIDO'.

            WHEN v.numero_pedido IS NOT NULL THEN 'PEDIDO'


            -- REGRA 3: Se estava na agenda E tem motivo, é 'JUSTIFICATIVANAOVENDA'.

            WHEN v.motivo IS NOT NULL THEN 'JUSTIFICATIVANAOVENDA'

           

            ELSE 'VISITA AVULSA'

        END AS tipo_vinculo,

       

        v.observacao,

        v.numero_pedido,

        v.motivo,

        v.codigo_justificativa,

        v.evento_bruto_encontrado -- Campo extra para auditoria

    FROM

        VisitasComEventoBruto AS v

)

SELECT *

FROM VisitasComEventoBruto;




Notas de versão


Data

Versão anterior

Versão atual

Alteração

Motivo

13/11/2025

--

1.0

Criação do dicionário com a inclusão dos SQLs:

·        Visitas X Atendimentos

·        Agendamentos e visitas

·        Indicadores de agendamentos

·        Painel de auditoria - visitas

Melhoria MAXINDV-698

14/11/2025

1.0

1.1

Adição de exemplos SQL para eventos

·        Evento Pedido, Justificativa não Venda e Venda Avulsa

o   Realizado exemplo apenas fato_visitas_realizadas

o   Realizado exemplo com fato_eventos e fato_visitas_realizadas


Melhoria MAXINDV-625


Voltar


Artigo criado por Thiago Oliveira

  • No labels