2
respostas

Junção de tabelas com somatória e contagem

Tenho as seguintes tabelas:

Tabela campanha:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

CREATE TABLE `campanha` (
  `id_campanha` int(11) NOT NULL AUTO_INCREMENT,
  `ds_nome` varchar(255) DEFAULT NULL,
  `dt_local` datetime DEFAULT NULL,
  `user_sistema` varchar(255) DEFAULT NULL,
  `dt_inicio` datetime DEFAULT NULL,
  `dt_final` datetime DEFAULT NULL,
  `ativa` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id_campanha`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4;

Tabela questao:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

CREATE TABLE `questao` (
  `id_questao` int(11) NOT NULL AUTO_INCREMENT,
  `id_campanha` int(11) DEFAULT NULL,
  `ds_nome_questao` varchar(255) DEFAULT NULL,
  `ds_questao` varchar(255) DEFAULT NULL,
  `dt_local` datetime DEFAULT NULL,
  `user_sistema` varchar(255) DEFAULT NULL,
  `tipo` varchar(1) DEFAULT NULL,
  `tipo_resposta` varchar(20) DEFAULT NULL,
  `ordem_questao` int(11) DEFAULT NULL,
  PRIMARY KEY (`id_questao`)
) ENGINE=InnoDB AUTO_INCREMENT=179 DEFAULT CHARSET=utf8mb4;

Tabela voucher:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

CREATE TABLE `voucher` (
  `id_voucher` int(11) NOT NULL AUTO_INCREMENT,
  `id_campanha` int(11) DEFAULT NULL,
  `ds_voucher` varchar(255) DEFAULT NULL,
  `qt_voucher` int(11) DEFAULT NULL,
  `ativo` tinyint(1) DEFAULT NULL,
  `user_sistema` varchar(255) DEFAULT NULL,
  `dt_local` datetime DEFAULT NULL,
  PRIMARY KEY (`id_voucher`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4;

Estou tentando retornar a seguinte estrutura:

id_campanhads_nomedt_iniciodt_finalqt_vouchervoucher_ativovoucher_desativadoqt_quetoes
31O que você acha do refeitório09/11/202110/11/20210006
30Você está feliz em seu serviço08/11/202109/11/20210005
29Campanha nome exemplo04/11/202108/11/202110914

Montei o seguinte select no MySQL

SELECT DISTINCT

    a.id_campanha,
    a.ds_nome,
    a.dt_local,
    a.user_sistema,
    a.dt_inicio,
    a.dt_final,
    a.ativa,
    b.qt_voucher,

    SUM(case when b.ativo = 1 then 1 else 0 end) over(partition by b.id_campanha) as voucher_ativo,
    SUM(case when b.ativo = 0 then 1 else 0 end) over(partition by b.id_campanha) as voucher_desativado,

    count(c.id_campanha) over(partition by a.id_campanha) as qt_questoes

    FROM campanha a
    left join voucher b on a.id_campanha = b.id_campanha 
    left join questao c on a.id_campanha = c.id_campanha
    ORDER BY a.id_campanha

Mas meu retorno está assim: Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Não consigo uma somatório dos vouchers ativos e desativados correta com a função:

 SUM(case when b.ativo = 1 then 1 else 0 end) over(partition by b.id_campanha) as voucher_ativo,
 SUM(case when b.ativo = 0 then 1 else 0 end) over(partition by b.id_campanha) as voucher_desativado,

E contagem das questões por campanha com a função:

count(c.id_campanha) over(partition by a.id_campanha) as qt_questoes

O que está errado? Se alguém tiver outra lógica para montar esse select, por favor poderia me ajudar.

2 respostas

Olá, Evandro, tudo bem?

Peço desculpas pela demora no retorno.

Você pode tentar fazer algumas alterações na sua query, e verificar se funciona, como:

  • Você pode tentar utilizar apenas um CASE e no lugar de utilizar 1 e 0, você pode informar como ativado e desativado.
  • Você pode também, tentar utilizar a cláusula GROUP BY para agrupar o resultado pelo CASE.

Espero ter ajudado e bons estudos!

Bom dia,

Eu refiz minha consulta utilizando subselects e obtive o resultado esperado.

SELECT DISTINCT
    a.id_campanha,
    a.ds_nome,
    a.dt_local,
    a.user_sistema,
    a.dt_inicio,
    a.dt_final,
    a.ativa,
    b.qt_voucher,

    (select count(c.id_campanha) from questao c 
     where a.id_campanha = c.id_campanha) as qt_questoes,

    (select SUM(case when b.ativo = 1 then 1 else 0 end) 
    from voucher b where a.id_campanha = b.id_campanha) as voucher_ativo,
    (select SUM(case when b.ativo = 0 then 1 else 0 end) 
    from voucher b where a.id_campanha = b.id_campanha) as voucher_desativado

    FROM campanha a
    left join voucher b on a.id_campanha = b.id_campanha 

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software