Vista indexada
Una solución completamente nueva basada en Vistas indexadas es posible.
Una vista indexada es una vista que tiene un índice agrupado y los datos se almacenan en el disco.
Según tengo entendido, está tratando de mantener una suma de compras por artículo de producto almacenada en tblProduct
. He asumido que ItemCode
es el PK de tblProduct y ese ItemName
también se define allí (no podemos usar MAX
en una vista indexada). Entonces podemos definir una vista como esta:
CREATE VIEW dbo.vwTotalPurchases
WITH SCHEMABINDING -- must be schema bound, we cannot change underlying columns after creation
AS
SELECT
ItemCode,
SUM(Quantity) QuantityPurchased,
COUNT_BIG(*) CountPurchases -- if we group, must have count also, so that rows can be maintained
FROM dbo.tblPurchase -- must use two-part names
GROUP BY itemCode;
GO
Luego podemos crear un índice agrupado en él para conservarlo en el disco. SQL Server mantendrá el índice cada vez que se actualice la tabla base. Si no hay más filas en la agrupación (identificadas por el recuento 0), entonces la fila se elimina:
CREATE UNIQUE CLUSTERED INDEX PK_vwTotalPurchases ON dbo.vwTotalPurchases (ItemCode);
GO
Ahora, si queremos consultarlo, podemos unirnos a esta vista en tblProducts
(se unió a la izquierda porque es posible que no haya compras):
SELECT
p.ItemCode,
p.ItemName,
ISNULL(tp.QuantityPurchased, 0) QuantityPurchased,
ISNULL(tp.CountPurchases, 0) CountPurchases
FROM tblProducts p
LEFT JOIN vwTotalPurchases tp WITH (NOEXPAND) ON tp.ItemCode = p.ItemCode;
También podemos definir esto como una vista (no indexada, sino una vista estándar) para que la definición se pueda usar en cualquier lugar.
Nota sobre NOEXPAND
:
Si no está en SQL Server Enterprise o Developer Edition, debe usar la sugerencia WITH (NOEXPAND)
para forzarlo a usar el índice, de lo contrario consultará la base tblPurchase
en cambio. E incluso en esas ediciones, es mejor usar NOEXPAND
.
Consulte este artículo por Paul White sobre esto.