2011-01-13 1 views
1

Je contiennent des données comme ceci:Comment sélectionner parmi tableA la somme des nombres groupés de la tableB au-dessus de leur somme moyenne dans Oracle?

tableA.ID 
--------- 
1 
2 
3 

tableB.ID tableB.NUM 
-------------------- 
1   10 
1   15 
2   18 
3   12 
2   12 
2   15 
3   13 
1   12 

J'ai besoin pour sélectionner les ID tableA où la somme de leurs Nums à tableB est supérieure à la moyenne de toutes les sommes des ID tableA. En d'autres termes:

SUM ID=1 -> 10+15+12 = 37 
SUM ID=2 -> 18+12+15 = 45 
SUM ID=3 -> 12+13 = 25 

AVG ALL IDs -> (37+45+25)/3 = 35 

Le SELECT doit afficher uniquement ID 1 et 2 parce que 37> 35, 45> 35 mais 25 < 35.

C'est ma question actuelle qui fonctionne bien:

SELECT tableA.ID 
FROM tableA, tableB 
WHERE tableA.ID = tableB.ID 
HAVING SUM(tableB.NUM) > (
    SELECT AVG(MY_SUM) 
    FROM (
     SELECT SUM(tableB.NUM) MY_SUM 
     FROM tableA, tableB 
     WHERE tableA.ID = tableB.ID 
     GROUP BY tableA.ID 
    ) 
) 
GROUP BY tableA.ID 

Mais j'ai le sentiment qu'il pourrait y avoir un meilleur moyen sans tous ces SELECT imbriqués. Peut-être 2, mais 3 semble trop. Je me trompe probablement cependant.

Par exemple, pourquoi ne puis-je faire quelque chose de simple comme ceci:

SELECT tableA.ID 
FROM tableA, tableB 
WHERE tableA.ID = tableB.ID 
HAVING SUM(tableB.NUM) > AVG(SUM(tableB.NUM)) 
GROUP BY tableA.ID 

Ou ceci:

SELECT tableA.ID, SUM(tableB.NUM) MY_SUM 
FROM tableA, tableB 
WHERE tableA.ID = tableB.ID 
HAVING MY_SUM > AVG(MY_SUM) 
GROUP BY tableA.ID 
+0

BTW Vos données d'exemple manquent une ligne pour '2,12' je pense. –

+0

Vous avez raison, merci. –

Répondre

2

En SQL Server vous pouvez le faire. Je ne sais pas si cela fonctionne dans Oracle. Je suis sûr que je le saurai bientôt si ce n'est pas le cas!

WITH cte As (
SELECT 
     tableA.ID, 
     SUM(tableB.NUM) AS MY_SUM, 
     AVG(SUM(tableB.NUM)) over() As Average 
FROM tableA, tableB 
WHERE tableA.ID = tableB.ID 
GROUP BY tableA.ID 
) 
SELECT ID 
FROM cte 
WHERE MY_SUM > Average 
+0

Semble exagérer tous ces SUM() et OVER() ... –

+0

@Nazgulled - Il évite de faire le JOIN deux fois (au moins en théorie, je n'ai absolument aucune idée si elle est prise en charge dans Oracle et comment il serait implémenté si c'est) –

+0

Cela a fonctionné sur ma base de données exemple. Est-ce que je peux supposer qu'il ne se joindra pas deux fois ou que ce n'est peut-être toujours pas vrai? Et que fait exactement 'OVER()'? –

1

Cela devrait réduire d'un niveau

SELECT tableA.ID 
FROM tableA, tableB 
WHERE tableA.ID = tableB.ID 
GROUP BY tableA.ID 
HAVING SUM(tableB.NUM) > (
    SELECT SUM(tableB.NUM)/COUNT(DISTINCT tableA.ID) 
    FROM tableA, tableB 
    WHERE tableA.ID = tableB.ID 
) 
+0

Oubliez AVG() alors? Cela ressemble à une bonne solution ... Je vais juste attendre quelques heures de plus pour voir si quelqu'un trouve de bonnes alternatives. –

Questions connexes