web-dev-qa-db-fra.com

SQL Server "ne peut pas exécuter une fonction d'agrégation sur une expression contenant un agrégat ou une sous-requête", mais Sybase peut

Ce problème a été discuté auparavant, mais aucune des réponses ne résout mon problème spécifique car je traite des clauses where différentes dans les sélections internes et externes. Cette requête s'est très bien exécutée sous Sybase, mais donne l'erreur dans le titre de ce message lorsqu'elle est exécutée sous SQL Server. La requête est compliquée, mais le contour général de la requête est:

select sum ( t.graduates -
    ( select sum ( t1.graduates )
      from table as t1
      where t1.id = t.id and t1.group_code not in ('total', 'others' ) ) )
from table as t
where t.group_code = 'total'

Ce qui suit décrit la situation que j'essaie de résoudre:

  • tous les codes de groupe représentent les races, sauf pour "total" et "autres"
  • le code de groupe "total" représente le nombre total de diplômés de toutes les races
  • cependant, plusieurs courses sont manquantes, donc le nombre de diplômés de la course peut ne pas correspondre au nombre total de diplômés
  • ces données manquantes sont ce qui doit être calculé

Est-il possible de réécrire cela en utilisant des tables dérivées ou des jointures pour obtenir les mêmes résultats?

Mise à jour: J'ai créé exemples de données et 3 solutions à mon problème spécifique (2 influencés par sgeddes). Celui que j'ai ajouté implique le déplacement de la sous-requête corrélée vers une table dérivée dans la clause FROM. Merci pour l'aide les gars!

25
PillowMetal

Une option consiste à placer la sous-requête dans un LEFT JOIN:

select sum ( t.graduates ) - t1.summedGraduates 
from table as t
    left join 
     ( 
        select sum ( graduates ) summedGraduates, id
        from table  
        where group_code not in ('total', 'others' )
        group by id 
    ) t1 on t.id = t1.id
where t.group_code = 'total'
group by t1.summedGraduates 

Une meilleure option serait peut-être d'utiliser SUM avec CASE:

select sum(case when group_code = 'total' then graduates end) -
    sum(case when group_code not in ('total','others') then graduates end)
from yourtable

SQL Fiddle Démo avec les deux

35
sgeddes