2009-07-17 12 views
0

Ich versuche, Zeilenversionierung mithilfe einer indizierten Sicht durchzuführen, Datensätze nach Schlüssel und Zeitstempel zu gruppieren und den Datensatz max (timestamp) zu übernehmen. Das ist in Ordnung, aber die Abfrage, die ich verwendet habe (siehe die folgende Ansicht), macht einen Self-Join, dh sie kann nicht in einer indizierten Ansicht verwendet werden, was meiner Meinung nach für die Performance wesentlich ist. Gibt es eine Möglichkeit, die Abfrage neu zu schreiben, damit die Ansicht erfolgreich mit SCHEMABINDING erstellt werden kann?SQL GROUP BY: Abrufen des zuletzt aktualisierten Datensatzes für eine indizierte Sicht

Ich benutze 2005, aber eine 2008 einzige Lösung wäre auch in Ordnung.

IF EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[Items]')) 
    DROP VIEW [dbo].[Items] 
GO 
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ItemHistory]') AND type in (N'U')) 
    DROP TABLE [dbo].[ItemHistory] 
GO 
CREATE TABLE [dbo].[ItemHistory](
    [Key] [nchar](10) NOT NULL, 
    [Value] [int] NOT NULL, 
    [TimeStamp] Timestamp NOT NULL, 
    [LastUpdateBy] [varchar](50) NOT NULL CONSTRAINT [DF_ItemHistory_LastUpdateBy] DEFAULT (SUSER_NAME()), 
    [Deleted] BIT NOT NULL DEFAULT (0) 
    CONSTRAINT [PK_ItemHistory] PRIMARY KEY CLUSTERED 
    (
     [Key] ASC, 
     [TimeStamp] ASC 
    ) ON [PRIMARY] 
) 
GO 
CREATE VIEW dbo.Items 
--WITH SCHEMABINDING --doesnt work with the query below :(
AS 
    SELECT ih.[key], ih.[Value] FROM ItemHistory ih 
    INNER JOIN (
     SELECT [Key], Max([TimeStamp]) [TimeStamp] 
     FROM ItemHistory 
     GROUP BY [Key] 
    ) ih2 ON ih.[key] = ih2.[key] AND ih.[TimeStamp] = ih2.[TimeStamp] AND Deleted = 0 
GO 
INSERT INTO Items ([Key], [Value]) VALUES ('ItemA', 1) 
INSERT INTO Items ([Key], [Value]) VALUES ('ItemA', 2) 
INSERT INTO Items ([Key], [Value]) VALUES ('ItemA', 3) 

GO 
SELECT * FROM ItemHistory 
SELECT * FROM Items 

Antwort

2

Wenn Sie ItemHistory mit dbo.ItemHistory in der Items View-Definition ersetzen sollte es funktionieren.

Auch können Sie die folgende Abfrage möglicherweise besser ausführen, da es die Verwendung der MAX-Funktion vermeiden.

CREATE VIEW dbo.Items 
WITH SCHEMABINDING 
AS 
    SELECT ih.[key], ih.[Value] FROM dbo.ItemHistory ih 
    WHERE NOT EXISTS (SELECT [Key] 
     FROM dbo.ItemHistory AS ih2 
     WHERE ih.[key] = ih2.[key] AND ih.[TimeStamp] < ih2.[TimeStamp]) AND Deleted = 0 
GO 
+0

Sie Sir, sind ein Genie. Ich bin ein Idiot. Ich habe die Erstellungsnachricht nicht richtig gelesen. Would SELECT ih. [Key], ih. [Wert] FROM dbo.ItemHistory ih WHERE NOT EXISTS (TOP 1 [Taste] VON dbo.ItemHistory AS IH2 WHERE ih. [Key] = IH2 SELECT. [ Taste] UND ih. [Zeitstempel] mcintyre321

+0

Sie sind viel zu nett. Ich bin nicht sicher, ob die zusätzliche TOP 1-Klausel es schneller machen würde, da SQL Server hinter den Kulissen viele Optimierungen durchführt und die Ausführungspläne tatsächlich identisch sind. Als ein anderes Beispiel gibt es, soweit mir bekannt ist, keinen Unterschied zwischen der Verwendung von SELECT * und SELECT [Key] für die Unterabfrage hinsichtlich der Ausführungsgeschwindigkeit, da SQL Server nur daran interessiert ist, ob eine Zeile existiert oder nicht. – MikeD