首先,我不是 DBA,这篇文章包含一些难看 的 sql 代码。 :)
上下文
我有一个表,代表我所有的产品库存事件(在 SQL“TP_MOVI”中),从流程开始到结束。在这一行之后,一个产品(在 SQL“CODIGO”中)可能在多个地方(在 SQL“ARMAZEM”中)有余额。
在表中,我有所有类型的事件,我的工作是对其进行汇总,例如,直到当前日期或参数化日期为止所有产品的余额。我的逻辑是通过使用子句 LAST_VALUE() OVER()
获取所有产品+地点的最后记录),生成所有地点的余额。
我的表目前有超过 1,000,000 条记录,现在,当我尝试从该表中检索数据时,它会造成一些中断,当然,还会延迟检索数据。 我很确定是我的 SQL 代码不正确导致了这个问题,你们能帮我改进这段代码吗?
我一直在阅读关于声明WITH NO LOCK
的内容,它有帮助吗?
内容 - SQL 代码
CREATE TABLE [MOVIMENTACOES](
[ID] [int] IDENTITY(1,1) NOT NULL,
[DATA] [datetime] NULL,
[CODIGO] [varchar](20) NULL,
[ARMAZEM] [int] NULL,
[TP_MOVI] [varchar](10),
[QUANTIDADE] [float] NULL,
[SALDO] [float] NULL,
[ATV] [bit] NULL)
INSERT INTO [MOVIMENTACOES]([DATA],[CODIGO],[ARMAZEM],[TP_MOVI],[QUANTIDADE],[SALDO],[ATV])VALUES('2017-04-24 05:54:59.340','123456',18,'PROD',0,10,1)
INSERT INTO [MOVIMENTACOES]([DATA],[CODIGO],[ARMAZEM],[TP_MOVI],[QUANTIDADE],[SALDO],[ATV])VALUES('2017-04-24 05:54:59.340','123456',18,'PROD',10,15,1)
INSERT INTO [MOVIMENTACOES]([DATA],[CODIGO],[ARMAZEM],[TP_MOVI],[QUANTIDADE],[SALDO],[ATV])VALUES('2017-04-24 05:54:59.340','456789',19,'PROD',0,20,1)
INSERT INTO [MOVIMENTACOES]([DATA],[CODIGO],[ARMAZEM],[TP_MOVI],[QUANTIDADE],[SALDO],[ATV])VALUES('2017-04-24 05:54:59.340','456789',19,'PROD',20,15,1)
INSERT INTO [MOVIMENTACOES]([DATA],[CODIGO],[ARMAZEM],[TP_MOVI],[QUANTIDADE],[SALDO],[ATV])VALUES('2017-04-24 05:54:59.340','123456',28,'PROD',0,6,1)
INSERT INTO [MOVIMENTACOES]([DATA],[CODIGO],[ARMAZEM],[TP_MOVI],[QUANTIDADE],[SALDO],[ATV])VALUES('2017-04-24 05:54:59.340','123456',28,'SALE',6,-6,1)
SELECT
MOV.ID,
MOV.DATA, MOV.CODIGO, MOV.ARMAZEM, MOV.TP_MOVI,
MOV.SALDO,
MOV.QUANTIDADE,
MOV.SALDO + LAST_VALUE(MOV.QUANTIDADE) OVER(ORDER BY MOV.DATA ROWS UNBOUNDED PRECEDING) AS SALDO_ACUMULADO
FROM MOVIMENTACOES MOV
LEFT OUTER JOIN MOVIMENTACOES MOV2 ON
MOV2.CODIGO = MOV.CODIGO AND
MOV2.ARMAZEM = MOV.ARMAZEM AND
MOV2.ID > MOV.ID
AND MOV2.DATA <= '2017-04-25 07:00:00'
WHERE
MOV2.ID IS NULL
AND MOV.DATA <= '2017-04-25 07:00:00'
这里是模式和一些数据示例:http://rextester.com/XIXCB97220
最佳答案
根据您的评论和预期结果,您似乎只需要每个 (CODIGO,ARMAZEM)
组合的最新行(= 具有最高 ID 的行)。而您的 SALDO_ACUMULADO
计算与 SALDO + QUANTIDADE
完全相同。这转化为一个简单的 ROW_NUMBER:
WITH cte AS
(
SELECT
MOV.ID,
MOV.DATA, MOV.CODIGO, MOV.ARMAZEM, MOV.TP_MOVI,
MOV.SALDO,
MOV.QUANTIDADE,
MOV.SALDO + MOV.QUANTIDADE AS SALDO_ACUMULADO,
ROW_NUMBER() OVER(PARTITION BY CODIGO, ARMAZEM ORDER BY MOV.ID DESC) AS rn
FROM MOVIMENTACOES MOV
WHERE DATA <= '2017-04-25 07:00:00'
)
SELECT *
FROM cte
WHERE rn = 1
关于sql - 使用 last_value+over 的大型 sql 表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43611463/