2011-06-11 34 views
50

En una prueba en la universidad hubo una pregunta; es posible usar una función agregada en la cláusula SQL WHERE.Función agregada en SQL WHERE-Cláusula

Siempre pensé que esto no era posible y tampoco encuentro ningún ejemplo de cómo sería posible. Pero mi respuesta fue falsa y ahora quiero saber en qué casos es posible usar una función de agregado en el WHERE. Además, si no es posible, sería bueno obtener un enlace a la especificación donde se describe.

Respuesta

23

No ha mencionado el DBMS. Suponiendo que está utilizando MS SQL Server, he encontrado un mensaje de error T-SQL que se explica por sí:

"Un agregado no puede aparecer en la cláusula WHERE a menos que sea en una subconsulta contenida en una cláusula HAVING o una lista de selección, y la columna que se está agregada es una referencia externa"

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


Y un ejemplo de que es posible en una subconsulta.

Muestra todos los clientes y el orden más pequeño para aquellos que tienen 5 o más órdenes (y NULL para otros):

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 ; 

UPDATE.

Lo anterior se ejecuta en SQL-Server y MySQL pero no devuelve el resultado que esperaba. El siguiente es más cercano. Supongo que tiene que ver con que el campo customerid, GROUPed BY y utilizado en la combinación query-subquery es en el primer caso PRIMARY KEY de la tabla externa y en el segundo caso no.

Muestra todos los ID de cliente y número de pedidos para los que tienen 5 o más órdenes (y nulo para otros):

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 ; 
+0

Sí, no mencioné un DBMS porque no hay ninguno especificado. Simplemente dice SQL -_- – n3on

+0

. Creo que esta posibilidad se agregó en las especificaciones SQL-92. No tengo idea de cuando varios productos agregaron la funcionalidad. La prueba solo con MySQL y SQL-Server muestra un comportamiento ligeramente diferente (SQL-Server es más estricto y probablemente más cercano a las especificaciones). Sería interesante, si alguien más pudiera verificar otras implementaciones de SQL. –

5

consulta actualizada:

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

Se va a seleccionar todos excepto la última fila de la tabla t.

+1

Creo que esto dependerá del DBMS como mencionó Tim. En SQL estándar, tendrá que escribirlo como 'SELECT id FROM t WHERE id <(SELECT MAX (id) FROM t)' –

+0

Sí, tiene razón. Acabo de recordar que era posible desde mis primeros tutoriales de base de datos, donde se nos pedía que seleccionáramos las primeras 5 filas sin utilizar TOP o LIMIT o ROWNUM. – Chandranshu

+1

Sí, pero luego la función agregación está en la cláusula de selección de la subconsulta y no en el WHERE. Y creo que una subconsulta no se puede ver como una función agregada. – n3on

71

QUE TIENEN es como DONDE con funciones de agregado, o puede utilizar una subconsulta.

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

O

select EmployeeId, sum(amount) 
from Sales 
group by Employee 
where EmployeeId in (
    select max(EmployeeId) from Employees) 
+0

sí, que es posible con tener yo sé. Pero el DONDE fue dado. Creo que es una definición. – n3on

+0

¡Gracias! Justo lo que necesitaba saber y entender. Voto arriba – Lukas

+11

Gracias por 'TENER' la respuesta correcta a esto;) – vikingsteve

9

No puede utilizar un agregado directamente en una cláusula WHERE; para eso son las cláusulas HAVING.

Puede usar una subconsulta que contenga un agregado en la cláusula WHERE.

+0

Sé que es posible como subconsulta, pero no estoy seguro de si puedo decir que puedo usar una función agregada en DÓNDE ... creo que es una definición. – n3on

+0

@ n3on: Estoy de acuerdo ... Argumentaría que no es posible usar agregados directamente en una cláusula WHERE, como dije. Solo es posible usarlos como parte de una sub consulta, y eso no contaría como 'en una cláusula WHERE' en mi libro. Si das la respuesta matizada matizada, no veo cómo pueden culparte. Si se trata de una pregunta de elección múltiple, entonces estás más atascado. –

+1

Ver la respuesta de Tim. Es posible. –

0

Otra solución es Mueva el agregado fuction a Escalar definida por el usuario Función

Crea Tu Función:

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

DECLARE @TotalAmount INT 

SET @TotalAmount = (select SUM(SaleAmount) FROM Sales where [email protected]) 

RETURN @TotalAmount 

END 

Uso de funciones en la cláusula WHERE

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

Referencias:

1. 2.

Hope ayuda a alguien.

Cuestiones relacionadas