Quelqu'un peut-il expliquer le total en cours d'exécution et SQL autojointure dans ce tutoriel pour moi?
-
22-09-2019 - |
Question
Je suis en train de lire sur le tutoriel ici: http: //www.1keydata .com / sql / sql-running-totals.html et tout fait sens jusqu'à ce qu'il soudainement se incroyablement extrêmement ridiculement compliqué quand il est arrivé à classer, la médiane, les totaux en cours d'exécution, etc. quelqu'un peut-il expliquer en anglais clair comment cette les résultats de la requête dans un total en cours d'exécution? Merci!
La solution
Avant de commencer, je ne l'ai pas vu cela avant et il ne ressemble pas à une manière terriblement compréhensible pour accomplir un total en cours d'exécution.
D'accord, voici la requête du tutoriel:
SELECT a1.Name, a1.Sales, SUM(a2.Sales) Running_Total
FROM Total_Sales a1, Total_Sales a2
WHERE a1.Sales <= a2.sales or (a1.Sales=a2.Sales and a1.Name = a2.Name)
GROUP BY a1.Name, a1.Sales
ORDER BY a1.Sales DESC, a1.Name DESC;
Et la sortie de l'échantillon
Name Sales Running_Total
Greg 50 50
Sophia 40 90
Stella 20 110
Jeff 20 130
Jennifer 15 145
John 10 155
La partie simple de cette requête affiche les données de vente pour chaque employé. Tout ce que nous faisons est la sélection name
et sales
de chaque employé et de les commander par le montant de la vente (descendant). Cela nous donne notre liste de base.
Nous voulons maintenant pour le total en cours d'exécution, chaque ligne qui a déjà été affiché. Donc, nous nous associons à la table contre lui-même, sur chaque ligne qui aurait déjà été affiché:
WHERE a1.Sales <= a2.sales or (a1.Sales=a2.Sales and a1.Name = a2.Name)
Ensuite, nous utilisons la fonction d'agrégation SUM
et le groupe en conséquence. Une bonne façon de comprendre est que si vous regardez ce qui se passerait si vous n'avez pas utilisé la fonction de groupe. La ligne « Sophia » ressemblerait à ceci:
Name A1.Sales A2.Sales
Sophia 40 50
Sophia 40 40
Remarquez comment nous avons obtenu la ligne de vente de Greg? Le groupe somme, et le tour est joué!
L'espoir qui aide. Joe
Autres conseils
La première table se joint à lui-même, la jointure entraînant un nombre x de lignes, où x est le nombre de lignes qui ont la baisse des ventes totales que lui-même, ou le nom de la ligne est la même (toutes ces ventes avant la ligne que nous regardons, lors de la commande par le montant des ventes).
Il a ensuite des groupes sur les champs de la partie gauche de la jointure et résume les lignes que nous joignons à, donc un total en cours d'exécution. Pour voir comment cela fonctionne, vous pouvez l'exécuter sans la somme et le regroupement, pour voir les résultats bruts sont retournés.
Le SQL ci-dessus donne un résultat différent sur Sybase (ASE 15). Je pense que la raison est que la « commande par » n'est pas appliquée jusqu'à ce que le temps d'affichage. Voici le SQL et le résultat:
drop table Total_Sales
go
create table Total_Sales
(
Name char(15),
Sales int
)
INSERT INTO Total_Sales VALUES( 'John', 10 )
INSERT INTO Total_Sales VALUES( 'Jennifer', 15)
INSERT INTO Total_Sales VALUES('Stella', 20 )
INSERT INTO Total_Sales VALUES('Sophia', 40 )
INSERT INTO Total_Sales VALUES('Greg', 50 )
INSERT INTO Total_Sales VALUES('Jeff', 20 )
SELECT a1.Name, a1.Sales, SUM(a2.Sales) Running_Total
FROM Total_Sales a1, Total_Sales a2
WHERE a1.Sales <= a2.Sales or (a1.Sales=a2.Sales and a1.Name = a2.Name)
GROUP BY a1.Name, a1.Sales
ORDER BY a1.Sales DESC, a1.Name DESC
Résultat:
Name Sales Running_Total
Greg 50 50
Sophia 40 90
Stella 20 130 --note that two running totals are the same!
Jeff 20 130
Jennifer 15 145
John 10 155
Bob
Je reçois aussi la même sortie incorrecte comme Bob ci-dessus où les pauses de total vers le bas à Stella & Jeff, qui ont le même nombre de ventes. J'utilise SQL Server 2014 Management Studio Express. Je ne pense pas que la solution du site est correcte. Je ne la jointure basée sur le nom plutôt que sur les ventes et est venu avec ceux-ci, qui produisent un total de fonctionnement correct:
select a1.name
, a1.sales
, sum(a2.sales) 'running_total'
from #total_sales a1
inner join #total_sales a2 on a1.name <= a2.name
group by a1.name, a1.sales
order by sum(a2.sales);
Rendements:
name sales running_total
Stella 20 20
Sophia 40 60
John 10 70
Jennifer 15 85
Jeff 20 105
Greg 50 155
Vous pouvez également faire la variante ci-dessous si vous êtes mal à l'aise sur un total de tri. Il change l'ordre, mais le total en cours d'exécution est toujours correcte:
select a1.name
, a1.sales
, sum(a2.sales) 'running_total'
from #total_sales a1
inner join #total_sales a2 on a1.name >= a2.name
group by a1.name, a1.sales
order by a1.name;
Rendements:
name sales running_total
Greg 50 50
Jeff 20 70
Jennifer 15 85
John 10 95
Sophia 40 135
Stella 20 155