Dica do Mês – Identificando os números ausentes em uma sequência numérica

Olá pessoal, bom dia.

Tudo bem? Estamos no ultimo final de semana do mês de Setembro, a primavera chegou, já estamos vivendo a última estação do ano, 2019 voando, passando de forma extremamente rápida, o que muitas vezes não nos deixa perceber o quanto nossa vida é uma correria.

Mesmo com este correira, temos que tentar aproveitar todo tempo disponível dentro das 24 horas diárias para se dedicar também ao que gostamos de fazer, e por isso estou aqui novamente em mais um post do meu blog, que honra ter encontrar aqui neste sábado, sua presença é muito importante.

Ainda mais na sessão Dica do Mês, a qual foi criada á alguns anos com objetivo de compartilhar algo que possa ser considerada como uma dica ou melhores práticas para se trabalhar na área de banco de dados, mais especificamente com o Microsoft SQL Server.

A dica de hoje esta envolvida diretamente com os dados manipulados diariamente por empresas, instituições ou organizações públicas e privadas, me refiro a lançamento feitos através de um SIG – Sistema de Informação Gerencial ou ERP – Enterprise Resource Planning, que muitas vezes utilizamos para dar entrada em lançamento contábeis, movimentações fiscais e financeiras, ou “basicamente” cadastrar uma nota fiscal de recebimento de produto no almoxarifado da empresa.

Para facilitar o entendimento, e server como base de exemplo para nossa dica, dentre as mais diversas áreas, setores e departamentos que constituem uma empresa, selecione para esta dica, uma das mais tradicionais áreas conhecida por muitos como Controle de Estoque vinculado com os lançamentos contábeis.

Mais ainda não ficou claro o objetivo desta dica, não é mesmo? Tenho a certeza que não, mas tenha calma, você vai descobrir a seguir o que estou querendo te apresentar.

Sendo assim, sem mais delongas, vamos em frente, vou tentar mitigar a sua curiosidade e ao mesmo também satisfazer os meus objetivos. Seja bem-vindo ao post – Dica do Mês – Identificando os números ausentes em uma sequência numérica.


Introdução

Na busca pelo aumento dos lucros da empresa, vários são os caminhos que podem ser seguidos. Um deles, que merece muita da sua atenção, passa pela melhoria do controle de estoque.

O planejamento permite que a empresa não gaste dinheiro com produtos que ficarão guardados no estoque por muito tempo. Gastar com algo que ficará muito tempo parado, é deixar de investir em outras situações mais rentáveis e que tragam outros tipos de retorno a empresa.

Controle de Estoque

O controle de estoque em dia é de extrema importância para uma empresa apurar o seu movimento de entrada e saída de mercadorias. E, assim, ter informações precisas sobre a demanda que o mercado tem de seu produto, eventuais desvios e também sobre o lucro líquido obtido no final do mês contábil.

Ter um estoque controlado é saber que há a quantidade correta de produtos para que a empresa possa fluir corretamente e atender sua demanda do mercado, sem ter prejuízos com perdas. O que parece óbvio nem sempre é para muitos gestores que ainda não sabem como realizar o controle de estoque corretamente.

Além de ajudar no gerenciamento da empresa, o controle de estoque oferece uma maior eficiência e organização de alguns dos processos internos de sua empresa. Ele também diminui desperdícios, tanto de tempo e energia na hora de fazer gestão quanto de seus recursos financeiros.

O estoque pode ser, geralmente, de duas modalidades diferentes. Uma é de matérias-primas para a produção industrial de grande ou pequeno porte. A outra, de produtos finais prontos para a comercialização no varejo.

Lançamentos Contábeis

Cada movimentação entre posições de estoque associadas a diferentes contas contábeis gera automaticamente um lançamento contábil.
Há dois tipos de movimentação:
1. Primária de quantidade e/ou valor: Em que a origem é uma conta (ou não há origem, como no caso de criação de uma OP, sem valor) e não um estoque. Exceção: se a movimentação for de devolução ou estorno, então a movimentação não é primária, mesmo que a origem seja uma conta.
O valor de um movimentação primária pode ser considerado como “uma imposição vinda de fora”, não sendo resultante de outra movimentação. Uma movimentação primária não acumula valor de outras.
O fato de uma NF gerar uma movimentação decorre de sua Operação fiscal, que possui uma propriedade “gera movimentação”.
Exemplos de movimentações primárias:
– Recebimento de NFs de itens comprados, de frete ou consultoria; e
– Criação de uma OP.
2 – Secundária: Movimentação entre diferentes locais  internos da empresa, sem trocas de valor com entidades externas. A movimentação secundária pode corresponder à propagação de uma movimentação primária, mas pode ocorrer mais tarde.
Exemplos de movimentação secundária:
– Baixa de insumos do estoque para ordens de produção;
– Propagação do custo da mão de obra, em quantidade (horas) e valor, que pode ser determinada depois da conclusão da ordem de produção, que corresponde a uma movimentação primária. Este valor inclui o rateio dos custos gerais, como por exemplo de energia elétrica ou administrativos, entre os centros de custos
– Propagação do custo do frete, originária de uma NF de frete, que pode chegar depois do recebimento do material. 
O recebimento da NF de frete é uma movimentação primária, mas a propagação do seu valor para os itens movimentados se faz através de movimentações secundária.
Agora que já conhecemos um pouco sobre as movimentações de controle de estoque, lançamentos contábeis e sua importância, avançaremos mais pouco pensando justamente em como nossos lançamentos feitos através de uma interface sistêmica pode apresentar esta ausência de números relacionadas com os dados cadastrados diretamente em um Banco de Dados, sendo assim, chegou a hora de construir nosso ambiente.

NOSSO AMBIENTE

Como de costume vamos utilizar um ambiente isolado dos demais bancos de dados que você possa conter, desta maneira nosso cenário será constituído dos seguintes elementos:

  • Banco de Dados: ControleDeEstoque; e
  • Tabela: Movimentacao.

Seguindo em frente, criaremos nosso banco de dados e logo na sequência começamos nossa análise, para tais procedimentos, utilizaremos o Bloco de Código 1 abaixo:

— Bloco de Código 1 – Criando nosso cenário —

— Criando o Banco de Dados —

Create Database ControleDeEstoque
Go

— Acessando o Banco de Dados —

Use ControleDeEstoque
Go

Acredito que este primeiro bloco de código tenha sido executado corretamente, o mesmo é algo bastante simples, nosso próximo passo será criar a Tabela Movimentacao.

Importante: Quero enfatizar, que antes de realizarmos a criação da referido tabela, que o ambiente proposto aqui, consiste basicamente em uma estrutura criada para a análise apresentada neste post, em nenhum momento, estarei levando em consideração qualquer regra de negócio, definições de relacionamento de dados, ou até mesmo a existência das tabelas que armazenem os dados de Produtos, Lançamentos Contábeis entre outros. Ressalto que o pensamento aqui aplicado é meramente uma representação de como pode se ocorrer a ausência numêrica ao longo do tempo em nossos sistemas.

Após este importante esclarecimento, vamos utilizaremos o Bloco de Código 2 apresentando a seguir, para criar a tabela Movimentacao:

— Bloco de Código 2 – Criando a Tabela Movimentacao —
Create Table Movimentacao
(CodigoMovimentacao Int Primary Key Identity(1,1),
CodigoProduto Int Not Null,
 CodigoLancamentoContabil Int Not Null,
DataMovimentacao Date Default GetDate())
Go

Observe que nossa tabela Movimentacao é composta por quatro colunas:

  1. CodigoMovimentacao: Chave Primária, utilizada para o controle sequencial dos nossos lançamentos;
  2. CodigoProduto: Código numérico utilizado para diferenciar um produto de outro de acordo com o cadastro de produto;
  3. CodigoLancamento: Código numérico sequencial, que identifica o lançamento de acordo com sua data de movimentação;
  4. DataMovimentacao: Data atual da movimentação, considerando o dia em o que mesmo foi inserido ou atualizado.

Nossa tabela esta criada, e pronta para receber alguns dados que estarão compondo nossa massa de dados como fonte de estudo e análise, em adicional vamos fazer uso do Bloco de Código 3 apresentado abaixo:

— Bloco de Código 3 – Inserindo a massa de dados na Tabela Movimentacao —
Insert Into Movimentacao (CodigoLancamentoContabil, CodigoProduto)
Values (1,1),(2,1),(3,1),(4,1),
(1,2),(2,2),(3,2),(4,2),
(1,3),(2,3),(3,3),(4,3)
Go

— Consultando os dados —
Select CodigoMovimentacao, CodigoLancamentoContabil, CodigoProduto, DataMovimentacao
From Movimentacao
Go

A Figura 1 abaixo, ilustra esta pequena massa de dados inserida na tabela Movimentação, a qual neste momento apresenta um total de 12 linhas de registros lógicos armazenados:
Figura 1 – Massa de dados inseridos na Tabela Movimentacao.

Muito bem, a partir de agora temos a nossa disposição alguns dados que poderão nos ajudar a exemplicar a ausência de números existentes dentro de uma sequência numérica de lançamentos manipulados através de uma interface sistêmica.

Para exemplicar este cenário, vamos fazer uso de um dos comandos mais tradicionais existentes nos SGBDs – Sistemas Gerenciadores de Bancos de Dados, me refiro ao comando Delete, sendo este o elemento que vai permiter criar um gap (ausência, diferência ou lacuna) no intervalo numérico de nossos lançamentos, utilizaremos então o Bloco de Código 4 logo na sequência:

— Bloco de Código 4 – Removendo alguns lançamentos para similar a ausência numérica —

Delete From Movimentacao
Where CodigoProduto = 2
And CodigoLancamentoContabil = 1
Go
Delete From Movimentacao
Where CodigoProduto = 3
And CodigoLancamentoContabil = 2
Go
Delete From Movimentacao
Where CodigoProduto = 3
And CodigoLancamentoContabil = 3
Go
Até aqui tudo tranquilo? Eu acredito que sim, neste momento removemos três linhas de registro lógicos que fazem referência aos nossos lançamentos existentes na tabela de Movimentacao, os quais foram executados de forma separada em três trechos de código através do comando Delete, neste momento estabelecemos de forma simples a ocorrência da ausência numérica de lançamentos em nossa tabela de acordo com as colunas: CodigoLancamentoContabil e CodigoProduto.
Claro que neste cenário, fica fácil identificar esta ausência, na verdade devemos imaginar este tipo de procedimento sendo executado nos mais variados setores e departamentos de uma empresa, não de forma direta em um banco de dados e sim através de um Sistema de Gestão.
De que maneira poderíamos tentar ter uma visão neste momento, de quantos registros estão cadastrados para cada produto, bem como o valor inicial e final de lançamentos contábeis.
Para tentar responder esta curiosidade dispertada após o uso do comando Delete, poderemos executar o Bloco de Código 5 a seguir:
— Bloco de Código 5 – Identificando as quantidades de lançamentos contábeis por produtos —
Select M.CodigoProduto,
           Min(CodigoLancamentoContabil) As MenorLancamentoCadastrado,
           Max(CodigoLancamentoContabil) As MaiorLancamentoCadastrado,
           Count(CodigoLancamentoContabil) As QuantidadeLancamento
From Movimentacao M
Group By M.CodigoProduto
Go
Observe que este bloco de código é bem simples, estamos fazendo uso das tradiconais funções de agregação de valores Min(), Max() e Count() as quais respectivamente nos permitem identificar:
  • Min – O menor número de lançamento contábil;
  • Max – O maior número de lançamento contábil; e
  • Count – A quantidade de lançamentos neste momento inseridadas na nossa tabela.

Após a execução do Bloco de Código 5, teremos um resultado similar obter conforme ilustra a Figura 2 abaixo:

Figura 2 – Quantidades de lançamentos contábeis por produtos.

Estamos quase no final desta longa caminhada, que começou na manhã deste sábado, já estamos entrando na madrugada de domingo, este post esta dando um certo trabalho além da conta, kkkkkk…….

Avançando mais um pouco, chegou a hora da verdade, momento de se identificar os números ausentes em nossa sequência de lançamentos contábeis, antes de apresentar a opção escolhida, quero destacar que durante o decorrer deste dia testei e analisei diversas maneira e técnicas para tentarmos utilizar, sou sincero a dizer que não conseguir bater o martelo em qual seria a melhor pois isso vai depender em muito do ambiente, maneira com que os dados são inseridos, relacionamentos e propriamente consultados.

Para nosso pequeno ambiente de teste tomei a decisão de criar uma Stored Procedure denominada P_IdentificarSequenciaNumerica, sendo ela o recurso que iremos utilizar para identificar e apresentar toda estrutura de sequencia numérica existente para um determinado produto tendo como base seus lançamentos contábeis.

Sem demais delongas, vamos fazer uso do Bloco de Código 6, responsável em criar nossa Stored Procedure:

— Bloco de Código 6 – Criando a Stored Procedure P_IdentificarSequenciaNumerica —  

Create Or Alter Procedure P_IdentificarSequenciaNumerica (@CodigoProduto Int)
As
Begin
 Declare @ContadorDeLancamento TinyInt,
@QuantidadeDeLancamentos TinyInt,
@Comando NVarchar(500)=”
 Select @ContadorDeLancamento=(IIf(Min(CodigoLancamentoContabil)>1,1,Min(CodigoLancamentoContabil))),
@QuantidadeDeLancamentos=(Max(CodigoLancamentoContabil))
From Movimentacao
Where CodigoProduto = @CodigoProduto
  While @ContadorDeLancamento <= @QuantidadeDeLancamentos
Begin If Exists (Select CodigoLancamentoContabil From Movimentacao
                Where CodigoProduto = @CodigoProduto
       And CodigoLancamentoContabil = @ContadorDeLancamento)
 Set @Comando=@Comando+’ Select ‘+Concat(@CodigoProduto,’ As CodigoProduto, ‘,@ContadorDeLancamento,’                                           As CodigoLancamentoContabil,’,”’Lançamento cadastrado” As Status’)
Else
Set @Comando=@Comando+’ Select ‘+Concat(@CodigoProduto,’ As CodigoProduto,                                 ‘,@ContadorDeLancamento,’ As CodigoLancamentoContabil,’,”’Lançamento não cadastrado” As Status’)
 Set @ContadorDeLancamento +=1
 If @ContadorDeLancamento <=@QuantidadeDeLancamentos
Set @Comando=@Comando +’ Union ‘
Else
Set @Comando=@Comando
End
 EXEC sys.sp_executesql @stmt = @Comando,
                                       @params = N’@CodigoProduto Int’,
                                       @CodigoProduto =@CodigoProduto 
End

Não vou descrever sobre toda estrutura de código utilizado pela P_IdentificarSequenciaNumerica, basicamente ela recebe como parâmetro de entrada de valores o código do produto, identifica a quantidade máxima de lançamentos que foram inseridos para este mesmo produto, e durante sua execução a cada volta do comando While, uma query dinâmica é criada, ao final toda estrutura de código esta montada para ser executada.
Vale ressaltar que devemos sempre se preocupar com possíveis ocorrências de SQL Injection, sendo assim, avalie o uso de querys dinâmicas em seu ambiente, como eu já destaquei este post somente demonstrar um ambiente de testes e forma de uso de comando é possível identificar a ocorrência de ausências numéricas, como dica, sempre que for trabalhar com querys dinâmicas preficar executar sua query através do comando SP_ExecuteSQL dentro do código fonte da Stored Procedure.
Para finalizar nossa caminhada, vamos executar a Stored Procedure, fique a vontade para escolher entre os comandos Exec ou Execute, para cada uma das opções o Microsoft SQL Server vai retornar em tela o mesmo resultado, eu optei por utilizando o tradicional e clássico Exec, conforme o Bloco de Código 7 apresenta:
— Bloco de Código 7 – Executando a Stored Procedure P_IdentificarSequenciaNumerica —
Exec P_IdentificarSequenciaNumerica 3 — Estamos informando o código de produto 3 —
Go

Ao executar o bloco de código 7, o SQL Server através da ferramenta que você esta utilizando para acesso seja ela o Management Studio ou Azure Data Studio, deverá apresentar um result set similar ao ilustrado pelo Figura 3 a seguir:
Figura 3 – Processamento da Stored Procedure P_IdentificarSequenciaNumerica.
Enfim, chegamos ao final desta longa caminhada? Ainda não kkkkkk, vou deixar um brinde para você, em adicional ao uso da Stored Procedure temos uma outra possibilidade que eu gosto muito e sinceramente falando acho mais elegante, me refiro ao uso das CTEs – Common Table Expression, recurso adicionado a partir do Microsoft SQL Server 2005 que trouxe uma flexibilidade, inteligência e rapidez para o produto acima do que podíamos imaginar.
A seguir apresento o Bloco de Código 8, utilizado para a implementação de um CTE recursive denonimada CTEIdentificarSequenciaNumerica, a qual vai retornar o mesmo result set apresentado pelo Stored Procedure que implementamos anteriormente, mas não estaremos fazendo uso do bloco de execução While, o que pode ser considerado um bloco de código mais ágil no que se refere a processamento e menos consumidor de memória:
— Bloco de Código 8 – Implementando a CTEIdentificarSequenciaNumerica —
Declare  @CodigoProduto TinyInt = 1 — Informe aqui o código do produto,
@QuantidadeLancamentosContabeis TinyInt
Set @QuantidadeLancamentosContabeis= (Select Max(CodigoLancamentoContabil) From Movimentacao Where CodigoProduto = @CodigoProduto Group By CodigoProduto)
— Declarando a CTE Recursiva —
;With CTEIdentificarSequenciaNumerica (CodigoProduto, NumeroSequencial)
As
(
Select @CodigoProduto As CodigoProduto, 1 As NumeroSequencial

 Union All

Select CodigoProduto, NumeroSequencial+1 From CTEIdentificarSequenciaNumerica
Where NumeroSequencial < @QuantidadeLancamentosContabeis
)

— Executando verificando os lançamento cadastrados —
Select C.CodigoProduto, C.NumeroSequencial, ‘Lançamentos Cadastrados’ As Status
From CTEIdentificarSequenciaNumerica C
Where C.NumeroSequencial In (Select CodigoLancamentoContabil From Movimentacao Where CodigoProduto = C.CodigoProduto)
Union
— Executando verificando os lançamento não cadastrados —
Select C.CodigoProduto, C.NumeroSequencial, ‘Lançamentos não Cadastrados’ As Status
From CTEIdentificarSequenciaNumerica C
Where C.NumeroSequencial Not In (Select CodigoLancamentoContabil From Movimentacao Where CodigoProduto = C.CodigoProduto)
Go

Importante: Nossa CTEIdentificarSequenciaNumerica utiliza o conceito de recursividade para de forma única e exclusiva gerar todo sequência numérica de lançamentos contábeis de acordo com o valor informado na variável @codigoproduto, desta forma, teremos a relação de números sequenciais independentes da existência ou não do lançamento, algo que vai nos permitir identificar e apresentar os lançamentos cadastrados e os ausentes denominados não cadastrados. Outro ponto de atenção, se relaciona aos dois blocos do comando Select, os quais respectivamente validam em tempo de execução se o lançamento encontra-se nesta momento cadastrado ou não cadastrado.

A Figura 4 abaixo, ilustra o resultado obtido após a execução da CTEIdentificarSequenciaNumerica:
Figura 4 – Relação de lançamentos contábeis retornados pela executação da CTEIdentificarSequenciaNumerica.
Aqui esta o meu brinde, neste mesmo post você pode identificar e aplicar duas formas diferentes de se obter a mesma análise e o mesmo conjunto de resultados, com certeza aprendemos muito hoje.
Ufa, agora sim, encerramento nossa caminhada…. Meu deus, estou super cansado, este post foi tenso, cansativo e muito desafiador, demorei um bom tempo para tentar implementar algo simples e de fácil aceitação e compreensão.
Seguindo a tradição dos posts anteriores publicados neste sessão, antes de encerrarmos, gostaria de contar com a sua participação, respondendo a enquete abaixo:
Pense em uma outra forma de implementação para este mesmo cenário, dentre as opções apresentadas na enquete acima, posso dizer que não será algo muito fácil de ser elaborado, com certeza você vai aprender muito.
Com isso chegamos ao final de mais um post da sessão Dica do Mês, espero que você tenha gostado, eu como de costume gostei muito. 

REFERÊNCIAS

The SQL of Gaps and Islands in Sequences

Create a Stored Procedure – SQL Server | Microsoft Docs

Aggregate Functions (Transact-SQL) – SQL Server …

POSTS ANTERIORES

CONCLUSÃO

Como de costume, tenho um imenso prazer em poder compartilhar um pouco das minhas experiências, estudos e conhecimentos que estou diariamente formando sobre este fantástico Sistema Gerenciador de Banco de Dados chamado Microsoft SQL Server.

Posso dizer que este foi o posts mais trabalhoso já publicado neste blog, o mesmo começou na manhã do sábado dia 28/09 e terminou na madrugada de domingo dia 29/09, uma simples ideia que inicialmente parecia que seria rapidamente resolvida, mas no decorrer do post me surpreendeu de forma totalmente inesperada, cheguei até a pensar em desistir, mas jamais devemos nos deixar se sentir vencidos ou incapazes.

Neste post você pode evidenciar como o Microsoft SQL Server nos permite para um determinado cenário, fazer uso das mais diversas e variadas análises, dentre elas, como podemos trabalhar com uma das áreas mais importantes de uma empresa o Controle de Estoque, foi possível conhecer um pouco mais sobre assunto, como também sobre os lançamentos contábeis, tivesse a possibilidade de simular a exclusão de registros lógicos para forçar a ocorrência de pequenos saltos ou lacunas de valores de dados que poderiam ser reconhecidas para ausências numéricas.

No decorrer do post, apresentei o uso das funções de agregação como forma de identificar alguns dados secundários com quantidade de lançamentos, valor máximo de lançamento, algo que em algo momento poderá lhe ser útil, no final do post, ficamos um de um dos recursos mais tradicionais do SQL Server, utilizamos uma Stored Procedure que nos permitiu identificar a ausência dos lançamentos contábeis que excluímos manualmente através do comando Delete.

Como brinde ao leitor, fizemos uso uso de uma CTE recursiva, considerada por 9 de cada 10 DBAs, uma das mais elegantes formas de implementação e manipulação de dados em tempo real alocados em memória sem necessitar de criação de tabelas ou uso de cursors.

Desta forma chegamos ao final deste desafiador post e mais uma vez saimos vencedores.

Este é o fantástico Microsoft SQL Server, produto tão fascinante que a cada dia eu não consigo deixar de querer estudar e conhecer mais ainda.

Agradecimentos

Agradeço a você por sua atenção e visita ao meu blog. Fique à vontade para enviar suas críticas, sugestões, observações e comentários.

Nos encontramos no próximo post da sessão Dica do Mês a ser publicado em breve.

Um forte abraço.

Até mais.

Autor: Junior Galvão - MVP

Profissional com vasta experiência na área de Tecnologia da Informação e soluções Microsoft. Pós-Graduado no Curso de Gestão e Engenharia de Processos para Desenvolvimento de Software com RUP na Faculdade FIAP – Faculdade de Informática e Administração Paulista de São Paulo. Graduado no Curso Superior em Gestão da Tecnologia de Sistemas de Informação pela Uninove – Campus São Roque. Formação MCDBA Microsoft, autor de artigos acadêmicos e profissionais postados em Revistas, Instituições de Ensino e WebSistes. Meu primeiro contato com tecnologia ocorreu em 1994 após meus pais comprarem nosso primeiro computador, ano em que as portas para este fantástico mundo se abriram. Neste mesmo ano, comecei o de Processamento de Dados, naquele momento a palavra TI não existia, na verdade a Tecnologia da Informação era conhecida como Computação ou Informática, foi assim que tudo começou e desde então não parei mais, continuando nesta longa estrada até hoje. Desde 2001 tenho atuado como Database Administrator – Administrador de Banco de Dados – SQL Server em tarefas de Administração, Gerenciamento, Migração de Servidores e Bancos de Dados, Estratégias de Backup/Restauração, Replicação, LogShipping, Implantação de ERPs que utilizam bancos SQL Server, Desenvolvimento de Funções, Stored Procedure, entre outros recursos. Desde 2008 exerço a função de Professor Universitário, para as disciplinas de Banco de Dados, Administração, Modelagem de Banco de Dados, Programação em Banco de Dados, Sistemas Operacionais, Análise e Projetos de Sistemas, entre outras. Experiência na Coordenação de Projetos de Alta Disponibilidade de Dados, utilizando Database Mirroring, Replicação Transacional e Merge, Log Shipping, etc. Trabalhei entre 2011 e 2017 como Administrador de Banco de Dados e Coordenador de TI no FIT – Instituto de Tecnologia da Flextronics, atualmente exerço a função de Professor Universitário na FATEC São Roque. CTO da Galvão Tecnologia, consultoria especializada em Gestão de TI, Administração de Servidores Windows Server, Bancos de Dados Microsoft SQL Server e Virtualização. Possuo titulação Oficial Microsoft MVP e reconhecimentos: MCC, MSTC e MIE.