Ich versuche, die Leistung der folgenden Abfrage zu verbessern:
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupId)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
) r ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
Momentan dauert es mit meinen Testdaten ca. eine Minute. Ich habe eine begrenzte Menge an Eingaben in Änderungen an der gesamten gespeicherten Prozedur, in der sich diese Abfrage befindet, aber ich kann sie wahrscheinlich dazu bringen, diese eine Abfrage zu ändern. Oder fügen Sie einen Index hinzu. Ich habe versucht, den folgenden Index hinzuzufügen:
CREATE CLUSTERED INDEX ix_test ON #TempTable(AgentID, RuleId, GroupId, Passed)
Und es hat die Zeit, die die Abfrage benötigt, tatsächlich verdoppelt. Ich erhalte den gleichen Effekt mit einem nicht klassifizierten Index.
Ich habe versucht, es wie folgt ohne Wirkung neu zu schreiben.
WITH r AS (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupId)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
)
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN r
ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
Als nächstes habe ich versucht, eine solche Fensterfunktion zu verwenden.
UPDATE [#TempTable]
SET Received = COUNT(DISTINCT (CASE WHEN Passed=1 THEN GroupId ELSE NULL END))
OVER (PARTITION BY AgentId, RuleId)
FROM [#TempTable]
An diesem Punkt fing ich an, den Fehler zu bekommen
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near 'distinct'.
Ich habe also zwei Fragen. Erstens können Sie mit der OVER-Klausel keine COUNT DISTINCT ausführen, oder habe ich sie einfach falsch geschrieben? Und zweitens kann jemand eine Verbesserung vorschlagen, die ich noch nicht ausprobiert habe? Zu Ihrer Information, dies ist eine SQL Server 2008 R2 Enterprise-Instanz.
BEARBEITEN: Hier ist ein Link zum ursprünglichen Ausführungsplan. Ich sollte auch beachten, dass mein großes Problem darin besteht, dass diese Abfrage 30-50 Mal ausgeführt wird.
https://onedrive.live.com/redir?resid=4C359AF42063BD98%21772
EDIT2: Hier ist die vollständige Schleife, in der sich die Anweisung befindet, wie in den Kommentaren angefordert. Ich überprüfe regelmäßig mit der Person, die damit arbeitet, den Zweck der Schleife.
DECLARE @Counting INT
SELECT @Counting = 1
-- BEGIN: Cascading Rule check --
WHILE @Counting <= 30
BEGIN
UPDATE w1
SET Passed = 1
FROM [#TempTable] w1,
[#TempTable] w3
WHERE w3.AgentID = w1.AgentID AND
w3.RuleID = w1.CascadeRuleID AND
w3.RulePassed = 1 AND
w1.Passed = 0 AND
w1.NotFlag = 0
UPDATE w1
SET Passed = 1
FROM [#TempTable] w1,
[#TempTable] w3
WHERE w3.AgentID = w1.AgentID AND
w3.RuleID = w1.CascadeRuleID AND
w3.RulePassed = 0 AND
w1.Passed = 0 AND
w1.NotFlag = 1
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupID)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
) r ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
UPDATE [#TempTable]
SET RulePassed = 1
WHERE TotalNeeded = Received
SELECT @Counting = @Counting + 1
END
count
ob die Spalte nullbar wäre. Wenn es irgendwelche Nullen enthält, müssen Sie 1 subtrahieren.