Fonction d'agrégation dans SQL WHERE-Clause

Dans un test à l'université, il y avait une question; est-il possible d'utiliser une fonction d'agrégation dans le SQL WHERE clause.

J'ai toujours pensé que ce n'était pas possible et je ne trouve pas non plus d'exemple sur la façon dont cela serait possible. Mais ma réponse a été marquée faux et maintenant, je veux savoir dans quels cas il est possible d'utiliser une fonction d'agrégation dans le WHERE. Aussi, si ce n'est pas possible, il serait bon d'obtenir un lien vers la spécification où il est décrit.

57
sql
demandé sur Simon Martin 2011-06-12 03:38:27

6 réponses

Vous n'avez pas mentionné le SGBD. En supposant que vous utilisez MS SQL-Server, j'ai trouvé un message D'erreur T-SQL qui est explicite:

" un agrégat peut ne pas apparaître dans Clause WHERE sauf si elle est dans un sous-requête contenue dans une clause HAVING ou une liste de sélection, et la colonne agrégé est une référence externe "

Http://www.sql-server-performance.com/


Et un exemple qu'il est possible dans une sous-requête.

Tout afficher clients et plus petite commande pour ceux qui ont 5 commandes ou plus (et NULL pour les autres):

SELECT a.lastname
     , a.firstname
     , ( SELECT MIN( o.amount )
         FROM orders o
         WHERE a.customerid = o.customerid
           AND COUNT( a.customerid ) >= 5
        )
        AS smallestOrderAmount
FROM account a
GROUP BY a.customerid
       , a.lastname
       , a.firstname ;

Mise à jour.

Ce qui précède s'exécute à la fois dans SQL-Server et MySQL mais il ne renvoie pas le résultat attendu. Le suivant est plus proche. Je suppose que cela a à voir avec le fait que le Champ customerid, groupé par et utilisé dans la jointure query-subquery est dans le premier cas la clé primaire de la table externe et dans le second cas ce n'est pas le cas.

Afficher tous les identifiants clients et le nombre de commandes pour ceux qui avoir 5 commandes ou plus (et NULL pour les autres):

SELECT o.customerid
     , ( SELECT COUNT( o.customerid )
         FROM account a
         WHERE a.customerid = o.customerid
           AND COUNT( o.customerid ) >= 5
        )
        AS cnt
FROM orders o
GROUP BY o.customerid ;
25
répondu Tim Schmelter 2011-06-12 01:53:39

Avoir est comme WHERE avec des fonctions d'agrégation, ou vous pouvez utiliser une sous-requête.

select EmployeeId, sum(amount)
from Sales
group by Employee
having sum(amount) > 20000

Ou

select EmployeeId, sum(amount)
from Sales
group by Employee
where EmployeeId in (
    select max(EmployeeId) from Employees)
82
répondu Jason Goemaat 2011-06-11 23:53:32

Vous ne pouvez pas utiliser un agrégat directement dans une clause WHERE; c'est à quoi servent les clauses HAVING.

Vous pouvez utiliser une sous-requête qui contient un agrégat dans la clause where.

9
répondu Jonathan Leffler 2011-06-11 23:56:11

Requête mise à jour:

select id from t where id < (select max(id) from t);

Il sélectionnera tout sauf la dernière ligne de la table t.

6
répondu Chandranshu 2012-10-10 14:34:22
SELECT COUNT( * )   
FROM agents   
HAVING COUNT(*)>3;  

Voir plus ci-dessous Lien:

3
répondu Samir Lakhani 2016-12-07 07:38:31

Une autre solution consiste à déplacer la fonction agrégée vers la fonction définie par L'utilisateur scalaire

Créez Votre Fonction:

CREATE FUNCTION getTotalSalesByProduct(@ProductName VARCHAR(500))
RETURNS INT
AS
BEGIN

DECLARE @TotalAmount INT

SET @TotalAmount = (select SUM(SaleAmount) FROM Sales where Product=@ProductName)

RETURN @TotalAmount

END

Utilisation de la Fonction dans la Clause where

SELECT ProductName, SUM(SaleAmount) AS TotalSales
FROM Sales
WHERE dbo.getTotalSalesByProduct(ProductName)  > 1000
GROUP BY Product

Références:

1. 2.

L'espoir aide quelqu'un.

1
répondu stom 2017-08-31 09:01:40