Filtrage des lignes avec les clauses WHERE et HAVING

Les clauses WHERE et HAVING d'une instruction SELECT gèrent les lignes des tables sources utilisées pour créer l'ensemble de résultats. WHERE et HAVING constituent des filtres. Elles spécifient une série de critères de recherche et seules les lignes y répondant sont utilisées pour créer l'ensemble de résultats. Ces lignes sont dites qualifiées pour participer à l'ensemble de résultats. Par exemple, la clause WHERE de cette instruction SELECT ne qualifie les lignes que pour un secteur de vente spécifique :

USE AdventureWorks2008R2;
GO
SELECT c.CustomerID, s.Name
FROM AdventureWorks2008R2.Sales.Customer c
JOIN AdventureWorks2008R2.Sales.Store s
ON s.BusinessEntityID = c.CustomerID
WHERE c.TerritoryID = 1;

La clause HAVING est généralement utilisée conjointement avec la clause GROUP BY pour filtrer les résultats des valeurs d'agrégation. La clause HAVING peut toutefois être spécifiée sans GROUP BY. La clause HAVING spécifie les filtres supplémentaires qui s'appliquent après ceux de la clause WHERE. Ces filtres peuvent être appliqués à une fonction d'agrégation utilisée dans la liste SELECT. Dans l'exemple suivant, la clause WHERE ne qualifie que les commandes concernant un produit dont le prix unitaire dépasse $100 et la clause HAVING limite ensuite le résultat aux commandes de plus de 100 unités.

USE AdventureWorks2008R2;
GO
SELECT OrdD1.SalesOrderID AS OrderID,
       SUM(OrdD1.OrderQty) AS "Units Sold",
       SUM(OrdD1.UnitPrice * OrdD1.OrderQty) AS Revenue
FROM Sales.SalesOrderDetail AS OrdD1
WHERE OrdD1.SalesOrderID in (SELECT OrdD2.SalesOrderID
    FROM Sales.SalesOrderDetail AS OrdD2
    WHERE OrdD2.UnitPrice > $100)
GROUP BY OrdD1.SalesOrderID
HAVING SUM(OrdD1.OrderQty) > 100;

Conditions de recherche dans les clauses WHERE et HAVING

Les conditions de recherche, ou qualifications, des clauses WHERE et HAVING peuvent comprendre les éléments suivants :

  • Des opérateurs de comparaison, tels que : =, < >, < et >

    Par exemple, la requête suivante récupère les lignes de la table Product pour les produits qui se trouvent dans la classe H.

    SELECT ProductID, Name
    FROM AdventureWorks2008R2.Production.Product
    WHERE Class = 'H'
    ORDER BY ProductID;
    
  • Intervalles (BETWEEN et NOT BETWEEN)

    Par exemple, la requête suivante récupère les lignes de la table Product dont les tarifs sont compris entre 100 $ et 500 $.

    SELECT ProductID, Name
    FROM AdventureWorks2008R2.Production.Product
    WHERE ListPrice BETWEEN 100 and 500
    ORDER BY ListPrice;
    
  • Listes (IN, NOT IN)

    Par exemple, la requête suivante récupère les produits appartenant à une liste de couleurs.

    SELECT ProductID, Name
    FROM AdventureWorks2008R2.Production.Product
    WHERE Color IN ('Multi', 'Silver')
    ORDER BY ProductID;
    
  • Critères spéciaux (LIKE et NOT LIKE)

    Par exemple, la requête suivante récupère les lignes de la table Product dont le nom du produit commence par les lettres Ch.

    SELECT ProductID, Name
    FROM AdventureWorks2008R2.Production.Product
    WHERE Name LIKE 'Ch%'
    ORDER BY ProductID;
    

    Notes

    Les seules conditions WHERE que vous pouvez utiliser sur des colonnes text sont les fonctions qui retournent un autre type de données, comme PATINDEX(), ou les opérateurs tels que IS NULL, IS NOT NULL, LIKE et NOT LIKE.

  • Valeurs NULL (IS NULL et IS NOT NULL)

    Par exemple, la requête suivante récupère les lignes de la table Customer dont l'ID du représentant commercial n'est pas NULL.

    SELECT s.Name
    FROM AdventureWorks2008R2.Sales.Customer c
    JOIN AdventureWorks2008R2.Sales.Store s
    ON c.CustomerID = S.CustomerID
    WHERE c.CustomerID IS NOT NULL
    ORDER BY s.Name;
    

    Notes

    Attention aux comparaisons de valeurs NULL. Par exemple, spécifier = NULL ne revient pas à spécifier IS NULL. Pour plus d'informations, consultez Valeurs NULL.

  • Tous les enregistrements (=ALL, >ALL, <= ALL, ANY).

    Par exemple, la requête suivante récupère les codes des commandes et des produits de la table SalesOrderDetail lorsque la quantité envoyée du produit est supérieure à la quantité envoyée pour tout autre produit de la classe H.

    USE AdventureWorks2008R2;
    GO
    SELECT OrdD1.SalesOrderID, OrdD1.ProductID
    FROM Sales.SalesOrderDetail OrdD1
    WHERE OrdD1.OrderQty > ALL
          (SELECT OrdD2.OrderQty
           FROM Sales.SalesOrderDetail OrdD2 JOIN Production.Product Prd
                 ON OrdD2.ProductID = Prd.ProductID
           WHERE Prd.Class = 'H');
    GO
    
  • Combinaisons de ces conditions (AND, OR, NOT)

    Par exemple, la requête suivante récupère tous les produits dont le tarif est inférieur à 500 $ ou dont la classe de produit est L et la ligne de produit est S.

    SELECT ProductID, Name
    FROM AdventureWorks2008R2.Production.Product
    WHERE ListPrice < 500
       OR (Class = 'L' AND ProductLine = 'S');
    

    Notez que lorsque vous recherchez une chaîne Unicode dans une clause WHERE, placez le caractère N avant la chaîne de recherche :

    SELECT BusinessEntityID 
    FROM AdventureWorks2008R2.Sales.Store 
    WHERE Name = N'Riders Company';