Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Anchor
Voltar
Voltar

Table of Contents
maxLevel9
minLevel3
stylenone
separatorpipe

Produto: maxInsights



4

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

Image Removed

Image Removed




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;

Image Removed




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


Artigos Relacionados

Content by Label
showLabelsfalse
max5
spacesBMX
showSpacefalse
sortmodified
reversetrue
typepage
cqllabel in ("coloque","Rótulo","Maxinsight","dicionário") and space = "BMX"
labelscerca eletrônica geolocalização portal executivo maxPromotor


Artigo criado por Thiago Oliveira