2009-10-22 8 views
17

Comment utiliser group by avec union dans t-sql? Je veux regrouper par la première colonne d'un résultat d'union, j'ai écrit le sql suivant mais cela ne fonctionne pas. Je ne sais pas comment référencer la colonne spécifiée (dans ce cas, c'est 1) du résultat de l'union. merci beaucoup.Comment utiliser group by avec union dans t-sql

SELECT * 
FROM (SELECT a.id , 
        a.time 
      FROM  dbo.a 
      UNION 
      SELECT b.id , 
        b.time 
      FROM  dbo.b 
     ) 
GROUP BY 1 

Répondre

14

GROUP BY 1

Je ne l'ai jamais connu GROUP BY pour soutenir l'utilisation ordinaux, seule ORDER BY. De toute façon, seul MySQL prend en charge GROUP BY n'incluant pas toutes les colonnes sans fonctions d'agrégat effectuées sur eux. Les ordinaux ne sont pas recommandés parce que s'ils sont basés sur l'ordre du SELECT - si cela change, votre ORDER BY (ou GROUP BY s'il est supporté).

Il n'est pas nécessaire d'exécuter GROUP BY sur le contenu lorsque vous utilisez UNION - UNION s'assure que les doublons sont supprimés; UNION ALL est plus rapide parce qu'il ne fonctionne pas - et dans ce cas vous auriez besoin GROUP BY ...

Votre requête ne doit être:

SELECT a.id, 
     a.time 
    FROM dbo.TABLE_A a 
UNION 
SELECT b.id, 
     b.time 
    FROM dbo.TABLE_B b 
6

Identifier la colonne est facile:

SELECT * 
FROM (SELECT id, 
        time 
      FROM  dbo.a 
      UNION 
      SELECT id, 
        time 
      FROM  dbo.b 
     ) 
GROUP BY id 

Mais cela ne résout pas le problème principal de cette requête: que faire avec les valeurs de la deuxième colonne lors du regroupement par le premier? Puisque (en particulier!) Vous utilisez UNION plutôt que UNION ALL, vous n'aurez pas lignes entièrement dupliquées entre les deux sous-tables de l'union, mais vous pouvez toujours très bien avoir plusieurs valeurs de temps pour une valeur de l'ID, et vous ne donnez aucune indication de ce que vous voulez faire - min, max, avg, somme, ou quoi ?! Le moteur SQL devrait donner une erreur à cause de cela (bien que certains comme mysql choisissent une valeur aléatoire parmi plusieurs, je pense que sql-server est meilleur que ça). Par exemple, changez la première ligne en SELECT id, MAX(time) ou similaire!

67

Vous devez aliaser la sous-requête. Ainsi, votre déclaration devrait être:

Select Z.id 
From (
     Select id, time 
     From dbo.tablea 
     Union All 
     Select id, time 
     From dbo.tableb 
     ) As Z 
Group By Z.id 
+1

merci @Thomas, c'est bien que c'est simple! – ghiboz

+7

Ceci devrait être la réponse acceptée. –

+1

le point clé est l'ajout d'alias à la sous-requête (AS Z) – isxaker