Se você já precisou fazer alguma query para agilizar o KARDEX do Protheus, hoje iremos demonstrar um exemplo de como fazer.
Esse exemplo foi criado e gentilmente disponibilizado pelo grande Bruno Cesar Mendes Jacinto ( LinkedIn ).
O primeiro passo é criar a função no SQL Server, sendo que o nome dela é KARDEX_SQL. Ela irá receber 4 parâmetros, a data da SB9, a data inicial de movimentações, a data final de movimentações e a filial.
Abaixo o código da função completa (substitua o 99 pelo seu grupo de empresas, por exemplo, SB2990 para SB2010):
USE [NOME_DA_SUA_BASE] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE OR ALTER FUNCTION [dbo].[KARDEX_SQL] ( @dtB9 char(8), @dtade char(8), @dtate char(8), @Filial char(2) ) RETURNS table AS RETURN ( SELECT B2_COD AS PRODUTO, B2_LOCAL AS ARMAZEM, B1_TIPO, 0 AS SALDO_INI, 0 AS ENTRADA_INI, 0 AS ENTRADA_FIM, 0 AS SAIDA_INI, 0 AS SAIDA_FIM, 0 AS CUSTO_INI, 0 AS CUS_ENT_INI, 0 AS CUS_ENT_FIM, 0 AS CUS_SAI_INI, 0 AS CUS_SAI_FIM FROM SB2990 (NOLOCK) AS B2 INNER JOIN SB1990 (NOLOCK) AS B1 ON B2_COD = B1_COD WHERE B2.D_E_L_E_T_ != '*' AND B1.D_E_L_E_T_ != '*' GROUP BY B2_COD, B2_LOCAL, B1_TIPO UNION ALL SELECT B9_COD AS PRODUTO, B9_LOCAL AS ARMAZEM, B1_TIPO, SUM(B9_QINI) AS SALDO_INI, 0 AS ENTRADA_INI, 0 AS ENTRADA_FIM, 0 AS SAIDA_INI, 0 AS SAIDA_FIM, SUM(B9_VINI1) AS CUSTO_INI, 0 AS CUS_ENT_INI, 0 AS CUS_ENT_FIM, 0 AS CUS_SAI_INI, 0 AS CUS_SAI_FIM FROM SB9990 (NOLOCK) AS B9 INNER JOIN SB1990 (NOLOCK) AS B1 ON B9_COD = B1_COD WHERE B9.D_E_L_E_T_ != '*' AND B1.D_E_L_E_T_ != '*' AND B9_DATA = @dtB9 AND B9_FILIAL = @Filial GROUP BY B9_COD, B9_LOCAL, B1_TIPO UNION ALL SELECT D1_COD AS PRODUTO, D1_LOCAL AS ARMAZEM, B1_TIPO, 0 AS SALDO_INI, ROUND(SUM(CASE WHEN D1_DTDIGIT BETWEEN @dtade AND @dtate-1 THEN D1_QUANT ELSE 0 END ),2) AS ENTRADA_INI, ROUND(SUM(CASE WHEN D1_DTDIGIT BETWEEN @dtade AND @dtate THEN D1_QUANT ELSE 0 END ),2) AS ENTRADA_FIM, 0 AS SAIDA_INI, 0 AS SAIDA_FIM, 0 AS CUSTO_INI, ROUND(SUM(CASE WHEN D1_DTDIGIT BETWEEN @dtade AND @dtate-1 THEN D1_CUSTO ELSE 0 END ),2) AS CUS_ENT_INI, ROUND(SUM(CASE WHEN D1_DTDIGIT BETWEEN @dtade AND @dtate THEN D1_CUSTO ELSE 0 END ),2) AS CUS_ENT_FIM, 0 AS CUS_SAI_INI, 0 AS CUS_SAI_FIM FROM SD1990 (NOLOCK) AS D1 INNER JOIN SF4990 (NOLOCK) AS F4 ON D1_TES = F4_CODIGO INNER JOIN SB1990 (NOLOCK) AS B1 ON D1_COD = B1_COD WHERE D1.D_E_L_E_T_ != '*' AND B1.D_E_L_E_T_ != '*' AND F4.D_E_L_E_T_ != '*' AND D1_DTDIGIT BETWEEN @dtade AND @dtate AND D1_FILIAL = @Filial AND D1_ORIGLAN != 'LF' AND F4.F4_TIPO = 'E' AND F4_ESTOQUE = 'S' GROUP BY D1_COD, D1_LOCAL, B1_TIPO UNION ALL SELECT D2_COD, D2_LOCAL AS ARMAZEM, B1_TIPO, 0 AS SALDO_INI, 0 AS ENTRADA_INI, 0 AS ENTRADA_FIM, ROUND(SUM(CASE WHEN D2_EMISSAO BETWEEN @dtade AND @dtate-1 THEN D2_QUANT ELSE 0 END ),2) AS SAIDA_INI, ROUND(SUM(CASE WHEN D2_EMISSAO BETWEEN @dtade AND @dtate THEN D2_QUANT ELSE 0 END ),2) AS SAIDA_FIM, 0 AS CUSTO_INI, 0 AS CUS_ENT_INI, 0 AS CUS_ENT_FIM, ROUND(SUM(CASE WHEN D2_EMISSAO BETWEEN @dtade AND @dtate-1 THEN D2_CUSTO1 ELSE 0 END ),2) AS CUS_SAI_INI, ROUND(SUM(CASE WHEN D2_EMISSAO BETWEEN @dtade AND @dtate THEN D2_CUSTO1 ELSE 0 END ),2) AS CUS_SAI_FIM FROM SD2990 (NOLOCK) AS D2 INNER JOIN SF4990 (NOLOCK) AS F4 ON D2_TES = F4_CODIGO INNER JOIN SB1990 (NOLOCK) AS B1 ON D2_COD = B1_COD WHERE D2.D_E_L_E_T_ != '*' AND F4.D_E_L_E_T_ != '*' AND B1.D_E_L_E_T_ != '*' AND D2_EMISSAO BETWEEN @dtade AND @dtate AND F4.F4_TIPO = 'S' AND D2.D2_ORIGLAN != 'LF' AND D2_FILIAL = @Filial AND F4_ESTOQUE = 'S' GROUP BY D2_COD, D2_LOCAL, B1_TIPO UNION ALL SELECT D3_COD, D3_LOCAL AS ARMAZEM, B1_TIPO, 0 AS SALDO_INI, ROUND(SUM(CASE WHEN D3_TM <='499' AND D3_EMISSAO BETWEEN @dtade AND @dtate-1 THEN D3_QUANT ELSE 0 END ),2) AS ENTRADA_INI, ROUND(SUM(CASE WHEN D3_TM <='499' AND D3_EMISSAO BETWEEN @dtade AND @dtate THEN D3_QUANT ELSE 0 END ),2) AS ENTRADA_FIM, ROUND(SUM(CASE WHEN D3_TM >'499' AND D3_EMISSAO BETWEEN @dtade AND @dtate-1 THEN D3_QUANT ELSE 0 END ),2) AS SAIDA_INI, ROUND(SUM(CASE WHEN D3_TM >'499' AND D3_EMISSAO BETWEEN @dtade AND @dtate THEN D3_QUANT ELSE 0 END ),2) AS SAIDA_FIM, 0 AS CUSTO_INI, ROUND(SUM(CASE WHEN D3_TM <='499' AND D3_EMISSAO BETWEEN @dtade AND @dtate-1 THEN D3_CUSTO1 ELSE 0 END ),2) AS CUS_ENT_INI, ROUND(SUM(CASE WHEN D3_TM <='499' AND D3_EMISSAO BETWEEN @dtade AND @dtate THEN D3_CUSTO1 ELSE 0 END ),2) AS CUS_ENT_FIM, ROUND(SUM(CASE WHEN D3_TM >'499' AND D3_EMISSAO BETWEEN @dtade AND @dtate-1 THEN D3_CUSTO1 ELSE 0 END ),2) AS CUS_SAI_INI, ROUND(SUM(CASE WHEN D3_TM >'499' AND D3_EMISSAO BETWEEN @dtade AND @dtate THEN D3_CUSTO1 ELSE 0 END ),2) AS CUS_SAI_FIM FROM SD3990 (NOLOCK) AS D3 INNER JOIN SB1990 (NOLOCK) AS B1 ON D3_COD = B1_COD WHERE D3.D_E_L_E_T_ != '*' AND B1.D_E_L_E_T_ != '*' AND D3_ESTORNO != 'S' AND D3_FILIAL = @Filial AND D3_EMISSAO BETWEEN @dtade AND @dtate GROUP BY D3_COD, D3_LOCAL, B1_TIPO )
Como o retorno da função é uma tabela, para executar, basta dar um select no resultado dela, conforme o seguinte comando:
SELECT * FROM KARDEX_SQL('20211102', '20210101', '20211231', '01');
Abaixo um print do resultado:
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Fiz uma query dessa tbm realmente agiliza muito.
Opa, obrigado pelo comentário Lucas.
Abraços.
Muito bom, vai ajudar bastante, obrigado Dan e Bruno por compartilhar!
Opa, obrigado pelo comentário jovem.
Grande abraço.
Dan muito bom o exemplo, gostei bastante, tenho alguns exemplos aqui de Cursor no SQL e gostaria de compartilhar contigo, para onde posso enviar se vc achar interessante, publique no seu site.
Opa, fala Robson, tudo joia?
Pode mandar nos links de Contato – https://terminaldeinformacao.com/contato/
Ou no cabeçalho do site, também tem o WhatsApp, ai você envia junto com seu LinkedIn ou forma de contato que nós postamos aqui o artigo.
Grande abraço e obrigado pelo interesse.
Sensacional !! ! Outro Nível de programação.
Por acaso vocês tem uma query que cruza produto final vs consumido.
Obrigado pelo comentário Francisco, o Bruno manja mesmo.
Irei verificar e se encontrar algo, lhe aviso.
Muito útil, porém alguém teria uma versão “melhorada” que traga também as movimentações de endereçamento (SDB) ?
Boa tarde Luiz.
Obrigado pelo comentário. Ainda não tem, mas se você tiver uma base para disponibilizar os testes, podemos adaptar a query.
Ou se você também quiser adaptar e depois mandar ela revisada, ai eu atualizo aqui o artigo.
Um grande abraço.