J'ai une requête récursive qui fonctionne comme prévu pour calculer le coût moyen pondéré pour le calcul de l'inventaire. Mon problème est que j'ai besoin de plusieurs moyennes pondérées à partir de la même requête regroupées par colonnes différentes. Je sais que je peux résoudre le problème en le calculant plusieurs fois, un pour chaque colonne clé. Mais à cause des considérations de performance de requête, je veux qu'il soit traversé une fois. Parfois, j'ai 1M + lignes.Résultat groupé dans une requête récursive (SQL Server)
J'ai simplifié les données et remplacé la moyenne pondérée par une somme simple pour rendre mon problème plus facile à suivre.
Comment obtenir le résultat ci-dessous en utilisant cte récursif? N'oubliez pas que je dois utiliser une requête récursive pour calculer le coût moyen pondéré. Je suis sur le serveur SQL 2016.
Exemple de données (Id est aussi l'ordre de tri. Le Id et la clé est unique ensemble.)
Id Key1 Key2 Key3 Value
1 1 1 1 10
2 1 1 1 10
3 1 2 1 10
4 2 2 1 10
5 1 2 1 10
6 1 1 2 10
7 1 1 1 10
8 3 3 1 10
Résultat attendu
Id Key1 Key2 Key3 Value Key1Sum Key2Sum Key3Sum
1 1 1 1 10 10 10 10
2 1 1 1 10 20 20 20
3 1 2 1 10 30 10 30
4 2 2 1 10 10 20 40
5 1 2 1 10 40 30 50
6 1 1 2 10 50 30 10
7 1 1 1 10 60 40 60
8 3 3 1 10 10 10 70
EDIT
Après quelques critiques bien méritées, je dois être beaucoup mieux dans la façon dont je pose une question.
Voici un exemple et pourquoi j'ai besoin d'une requête récursive. Dans l'exemple, j'obtiens le résultat pour Key1, mais j'en ai aussi besoin pour Key2 et Key3 dans la même requête. Je sais que je peux répéter la même requête trois fois, mais ce n'est pas préférable.
DECLARE @InventoryItem AS TABLE (
IntentoryItemId INT NULL,
InventoryOrder INT,
Key1 INT NULL,
Key2 INT NULL,
Key3 INT NULL,
Quantity NUMERIC(22,9) NOT NULL,
Price NUMERIC(16,9) NOT NULL
);
INSERT INTO @InventoryItem (
IntentoryItemId,
InventoryOrder,
Key1,
Key2,
Key3,
Quantity,
Price
)
VALUES
(1, NULL, 1, 1, 1, 10, 1),
(2, NULL, 1, 1, 1, 10, 2),
(3, NULL, 1, 2, 1, 10, 2),
(4, NULL, 2, 2, 1, 10, 1),
(5, NULL, 1, 2, 1, 10, 5),
(6, NULL, 1, 1, 2, 10, 3),
(7, NULL, 1, 1, 1, 10, 3),
(8, NULL, 3, 3, 1, 10, 1);
--The steps below will give me the cost "grouped" by Key1
WITH Key1RowNumber AS (
SELECT
IntentoryItemId,
ROW_NUMBER() OVER (PARTITION BY Key1 ORDER BY IntentoryItemId) AS RowNumber
FROM @InventoryItem
)
UPDATE @InventoryItem
SET InventoryOrder = Key1RowNumber.RowNumber
FROM @InventoryItem InventoryItem
INNER JOIN Key1RowNumber
ON Key1RowNumber.IntentoryItemId = InventoryItem.IntentoryItemId;
WITH cte AS (
SELECT
IntentoryItemId,
InventoryOrder,
Key1,
Quantity,
Price,
CONVERT(NUMERIC(22,9), InventoryItem.Quantity) AS CurrentQuantity,
CONVERT(NUMERIC(22,9), (InventoryItem.Quantity * InventoryItem.Price)/NULLIF(InventoryItem.Quantity, 0)) AS AvgPrice
FROM @InventoryItem InventoryItem
WHERE InventoryItem.InventoryOrder = 1
UNION ALL
SELECT
Sub.IntentoryItemId,
Sub.InventoryOrder,
Sub.Key1,
Sub.Quantity,
Sub.Price,
CONVERT(NUMERIC(22,9), Main.CurrentQuantity + Sub.Quantity) AS CurrentQuantity,
CONVERT(NUMERIC(22,9),
((Main.CurrentQuantity) * Main.AvgPrice + Sub.Quantity * Sub.price)
/
NULLIF((Main.CurrentQuantity) + Sub.Quantity, 0)
) AS AvgPrice
FROM CTE Main
INNER JOIN @InventoryItem Sub
ON Main.Key1 = Sub.Key1
AND Sub.InventoryOrder = main.InventoryOrder + 1
)
SELECT cte.IntentoryItemId, cte.AvgPrice
FROM cte
ORDER BY IntentoryItemId
Qu'avez-vous essayé?C'est, où êtes-vous perdu? Veuillez consulter [Comment créer un exemple minimal, complet et vérifiable] (https://stackoverflow.com/help/mcve) et réviser votre question. – jhenderson2099
Si vous utilisez SQL Server 2012 ou version ultérieure, vous obtiendrez probablement de meilleures performances avec les fonctions de fenêtrage qu'avec la récursivité. –
vérifier ma dernière réponse. – KumarHarsh