Widok indeksowany
Całkowicie nowe rozwiązanie oparte na Widoki indeksowane jest możliwe.
Widok indeksowany to widok, który zawiera indeks klastrowy, a dane są faktycznie przechowywane na dysku.
Jak rozumiem, próbujesz zachować sumę zakupów na pozycję produktu przechowywaną w tblProduct
. Założyłem, że ItemCode
jest PK tblProduct i ten ItemName
jest również tam zdefiniowany (nie możemy użyć MAX
w widoku indeksowanym). Możemy więc zdefiniować taki widok:
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
Następnie możemy utworzyć na nim indeks klastrowy, aby zachować go na dysku. SQL Server będzie utrzymywać indeks za każdym razem, gdy nastąpi aktualizacja tabeli podstawowej. Jeśli w grupie nie ma więcej wierszy (oznaczonych liczbą 0), wiersz jest usuwany:
CREATE UNIQUE CLUSTERED INDEX PK_vwTotalPurchases ON dbo.vwTotalPurchases (ItemCode);
GO
Teraz, jeśli chcemy o to zapytać, możemy pozostawić dołączenie tego widoku do tblProducts
(dołącz po lewej, ponieważ może nie być zakupów):
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;
Możemy to również zdefiniować jako widok (nie indeksowany, ale standardowy widok), tak aby definicja była użyteczna w dowolnym miejscu.
Uwaga na temat NOEXPAND
:
Jeśli nie korzystasz z programu SQL Server Enterprise lub Developer Edition, musisz użyć wskazówki WITH (NOEXPAND)
aby zmusić go do korzystania z indeksu, w przeciwnym razie wyśle zapytanie do bazy tblPurchase
zamiast. I nawet w tych wydaniach najlepiej jest użyć NOEXPAND
.
Zobacz ten artykuł Paula White'a na ten temat.