comment effectuer plusieurs agrégations sur une seule requête SQL

J'ai une table avec trois colonnes:

GEOID, ParcelID et PurchaseDate.

Les PK sont GEOID et ParcelID qui est formaté comme suit:

GEOID PARCELID PURCHASEDATE 12345 AB123 1/2/1932 12345 sfw123 2/5/2012 12345 fdf323 4/2/2015 12346 dfefej 2/31/2022 <-New GEOID 

Ce dont j'ai besoin, c'est d'une agrégation basée sur GEOID. J'ai besoin de countr le nombre de ParcelID du mois dernier PER GEOID et je dois fournir un pourcentage de ce GEOID de tout le total vendu le mois dernier.

Je dois produire trois colonnes: GEOID Nbr_Parcels_Sold Percent_of_total

Pour chaque GEOID, j'ai besoin de savoir combien de colis vendus le mois dernier, et avec ce nombre, découvrez combien de pourcentage cela implique pour toutes les ventes.

Par exemple: s'il y avait 20 colis vendus le mois dernier, et 4 d'entre eux ont été vendus à partir de GEOID 12345, alors la sortie serait:

 GEOID Nbr_Parcels_Sold Perc_Total 12345 4 .2 (or 20%) 

J'ai des problèmes avec l'agrégation double. Le problème est que la table en question count plus de 8 millions d'loggings.

s'il y a un SQL Warrior ici qui a déjà vu ce problème, n'importe quelle sagesse serait grandement appréciée. Merci.

Que diriez-vous d'utiliser la sous-requête pour countr la sum

 WITH data AS ( SELECT * FROM [Table] WHERE YEAR(PURCHASEDATE) * 100 + MONTH(PURCHASEDATE) = 201505 ) SELECT GEOID, COUNT(*) AS Nbr_Parcels_Sold, CONVERT(decimal(18,8), COUNT(*)) / (SELECT COUNT(*) FROM data) AS Perc_Total FROM data t GROUP BY GEOID 

MODIFIER

Pour mettre à jour une autre table par le résultat, utilisez UPDATE sous WITH()

 WITH data AS ( SELECT * FROM [Table] WHERE YEAR(PURCHASEDATE) * 100 + MONTH(PURCHASEDATE) = 201505 ) UPDATE target SET Nbr_Parcels_Sold = source.Nbr_Parcels_Sold, Perc_Total = source.Perc_Total FROM [AnotherTable] target INNER JOIN ( SELECT GEOID, COUNT(*) AS Nbr_Parcels_Sold, CONVERT(decimal(18,8), COUNT(*)) / (SELECT COUNT(*) FROM data) AS Perc_Total FROM data t GROUP BY GEOID ) source ON target.GEOID = source.GEOID 

J'espère que vous utilisez SQL Server 2005 ou version ultérieure, auquel cas vous pouvez tirer parti de l'agrégation fenêtrée . Dans ce cas, l'agrégation fenêtrée vous permettra d'get le nombre total de ventes à côté des counts par GEOID et d'utiliser le total dans les calculs. Fondamentalement, la requête suivante renvoie seulement les counts:

 SELECT GEOID, Nbr_Parcels_Sold = COUNT(*), Total_Parcels_Sold = SUM(COUNT(*)) OVER () FROM dbo.atable GROUP BY GEOID ; 

L'appel COUNT(*) vous donne des counts par GEOID , selon la clause GROUP BY. Maintenant, l'expression SUM(...) OVER vous donne le nombre total général dans la même ligne que le nombre de détails . C'est la clause OVER vide qui indique à la fonction SUM d'additionner les résultats de COUNT(*) sur l'set du résultat. Vous pouvez utiliser ce résultat dans des calculs comme le résultat d'une autre fonction (ou d'une expression en général).

La requête ci-dessus renvoie simplement la valeur totale. Comme vous ne voulez pas la valeur elle-même mais un pourcentage pour chaque GEOID , vous pouvez simplement mettre l'appel SUM(...) OVER dans une expression:

 SELECT GEOID, Nbr_Parcels_Sold = COUNT(*), Percent_of_total = COUNT(*) * 100 / SUM(COUNT(*)) OVER () FROM dbo.atable GROUP BY GEOID ; 

Ce qui précède vous donnera des pourcentages entiers (tronqués). Si vous voulez plus de précision ou une représentation différente, n'oubliez pas de convertir le diviseur ou le dividende (facultativement les deux) en un type numérique non-entier, puisque SQL Server effectue toujours une division intégrale lorsque les deux opérandes sont des entiers.

Essayez ce qui suit. Il saisit le total des ventes dans une variable puis l'utilise dans la requête suivante:

 DECLARE @pMonthStartDate DATETIME DECLARE @MonthEndDate DATETIME DECLARE @TotalPurchaseCount INT SET @pMonthStartDate = <EnterFirstDayOfAMonth> SET @MonthEndDate = DATEADD(MONTH, 1, @pMonthStartDate) SELECT @TotalPurchaseCount = COUNT(*) FROM GEOIDs WHERE PurchaseDate BETWEEN @pMonthStartDate AND @MonthEndDate SELECT GEOID, COUNT(PARCELID) AS Nbr_Parcels_Sold, CAST(COUNT(PARCELID) AS FLOAT) / CAST(@TotalPurchaseCount AS FLOAT) * 100.0 AS Perc_Total FROM GEOIDs WHERE ModifiedDate BETWEEN @pMonthStartDate AND @MonthEndDate GROUP BY GEOID 

Je suppose que votre nom de table est GEOIDs. Changez la valeur de @pMonthStartDate en fonction de vous. Si vos PK sont comme vous le dites, ce sera une question rapide.