Imaginez que j'ai une table montrant les ventes de widgets AcMe et où ils ont été vendus. Il est assez facile de produire un rapport regroupant les ventes par pays. Il est assez facile de trouver le top 10. Mais ce que j'aimerais, c'est montrer le top 10, puis avoir une ligne finale en disant d'autres. Par exemple,
Ctry | Sales ============= GB | 100 US | 80 ES | 60 ... IT | 10 Other | 50
7 Réponses :
Union le top dix avec une jointure extérieure du top dix avec la table elle-même pour agréger le reste.
Je n'ai pas accès à SQL ici mais je vais hazzard une supposition: p> < Pré> xxx pré>
Bien sûr, s'il s'agit d'un haut de vis à changement rapide (10), alors vous verrouillez ou maintenez une copie du haut (10) pendant la durée de la requête. P> P> P> P> >
en pseudo SQL: Sélectionnez Top 10 des commandes en ventes SYNDICAT Sélectionnez «Autre», Somme (Ventes) Où Chérez-vous non dans (Sélectionnez Top 10 comme ci-dessus) P>
SELECT Ctry, sum(Sales) Sales FROM (SELECT COALESCE(T2.Ctry, 'OTHER') Ctry, T1.Sales FROM (SELECT Ctry, sum(Sales) Sales FROM Table1 GROUP BY Ctry) T1 LEFT JOIN (SELECT TOP 10 Ctry, sum(sales) Sales FROM Table1 GROUP BY Ctry) T2 on T1.Ctry = T2.Ctry ) T GROUP BY Ctry
J'ai essayé certaines des autres solutions ici, mais elles semblent être légèrement éteintes, soit la commande n'étant pas tout à fait raison.
Ma tentative d'une solution Microsoft SQL Server semble fonctionner correctement: P> Notez que dans mon exemple, je n'utilise que le top 2 plutôt que le top 10. Cela est simplement dû à mes données de test étant plutôt plus limitées. Vous pouvez facilement substituer le 2 pour A 10 dans vos propres données. P> Voici le script SQL pour créer la table: p> et mes données ressemblent ceci: p> Notez que le résultat de la requête est correctement commandé par l'agrégat de la valeur de vente et non le code de pays alphabétique, et que la catégorie "Autre" est toujours dure, même si Il s'agit d'une valeur de vente d'une valeur de vente le pousse normalement en haut de la liste. P> Je ne dis pas que c'est la solution la mieux (la plus optimale), cependant, pour le jeu de données que j'ai fourni qu'il semble que cela semble Bien travailler. p> p>
N'oubliez pas que en fonction de votre utilisation (et de votre volume / restrictions de base de données), vous pouvez obtenir les mêmes résultats à l'aide du code d'application (Python, noeud, C #, Java, etc.). J'ai fini par faire cela en C # par exemple: P> Bien sûr, il dépendra de votre cas d'utilisation code> mais hé, c'est possible.
// Mockup Class that has a CATEGORY and it's VOLUME
class YourModel { string category; double volume; }
List<YourModel> groupedList = wholeList.Take (5).ToList ();
groupedList.Add (new YourModel()
{
category = "Others",
volume = tempChartData.Skip (5).Select (t => t.qtd).Sum ()
});
Les solutions SQL pure à ce problème rendent plusieurs passes à travers les enregistrements individuels plus d'une fois. La solution suivante interroge uniquement les données une fois et utilise une fonction de classement SQL, Row_Number () pour déterminer si certains résultats appartiennent à la "Autre" catégorie. La fonction Row_Number () est disponible dans SQL Server depuis SQL Server 2008. Dans ma base de données, cela semble avoir abouti à une requête plus efficace. Veuillez noter que la "autre" ligne apparaîtra au-dessus de certaines lignes si le total des ventes "Autres" dépasse le TOP 10. Si cela n'est pas souhaité, certains ajustements devraient être apportés à cette requête:
SELECT CASE WHEN RowNumber > 10 THEN 'Other' ELSE Ctry END AS Ctry, SUM(Sales) as Sales FROM ( SELECT Ctry, SUM(Sales) as Sales, ROW_NUMBER() OVER(ORDER BY SUM(Sales) DESC) AS RowNumber FROM Table1 GROUP BY Ctry ) as AggregateQuery GROUP BY CASE WHEN RowNumber > 10 THEN 'Other' ELSE Ctry END ORDER BY SUM(Sales) DESC
Utilisation d'un véritable moteur SQL d'analyse, telle que Apache Spark, vous pouvez utiliser Expression de table commune avec code> pour faire:
with t as (
select rank() over (order by sales desc) as r, sales,city
from DB
order by sales desc
)
select sales, city, r
from t where r <= 10
union
select sum(sales) as sales, "Other" as city, 11 as r
from t where r > 10
Quelle saveur de SQL utilisez-vous? Différents produits auront des solutions différentes