Индексиран изглед
Изцяло ново решение, базирано на Индексирани изгледи е възможно.
Индексираният изглед е изглед, който има групиран индекс върху него и данните всъщност се съхраняват на диск.
Доколкото разбирам, вие се опитвате да запазите сума от покупки на продуктов артикул, съхранявана в tblProduct
. Предположих, че ItemCode
е PK на tblProduct и този ItemName
също е дефиниран там (Не можем да използваме MAX
в индексиран изглед). Така че можем да дефинираме изглед като този:
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
След това можем да създадем клъстерен индекс върху него, за да го запазим на диска. SQL Server ще поддържа индекса винаги, когато се случи актуализация на базовата таблица. Ако няма повече редове в групирането (идентифицира се чрез броя, който е 0), тогава редът се изтрива:
CREATE UNIQUE CLUSTERED INDEX PK_vwTotalPurchases ON dbo.vwTotalPurchases (ItemCode);
GO
Сега, ако искаме да го направим запитване, можем да се присъединим към този изглед наляво към tblProducts
(ляво присъединяване, защото може да няма покупки):
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;
Можем да дефинираме това и като изглед (не индексиран, а стандартен изглед), така че дефиницията да може да се използва навсякъде.
Забележка относно NOEXPAND
:
Ако не използвате SQL Server Enterprise или Developer Edition, трябва да използвате подсказката WITH (NOEXPAND)
за да го принуди да използва индекса, в противен случай ще направи заявка към базата tblPurchase
вместо. И дори в тези издания е най-добре да използвате NOEXPAND
.
Вижте тази статия от Пол Уайт за това.