首先,我不是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
答案 0 :(得分:3)
包含计算结果的计算列可能会提高SELECT
次。{
您可能还必须检查索引和键
我没有看到任何主键,例如,将列[ID]
设置为主键将有助于使用
它会在其上创建一个CLUSTERED INDEX
(这将用于减少SELECT
)的性能问题。
答案 1 :(得分:3)
根据您的评论&amp;预期的结果似乎只是想要每个(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