Агрегатная функция в SQL WHERE-предложение - PullRequest
64 голосов
/ 12 июня 2011

В тесте в университете возник вопрос; Можно ли использовать агрегатную функцию в предложении SQL WHERE.

Я всегда думал, что это невозможно, и я также не могу найти пример того, как это было бы возможно. Но мой ответ был помечен как ложный, и теперь я хочу знать, в каких случаях можно использовать статистическую функцию в WHERE. Также, если это невозможно, было бы неплохо получить ссылку на спецификацию, где она описана.

Ответы [ 6 ]

93 голосов
/ 12 июня 2011

HAVING похож на WHERE с агрегатными функциями, или вы можете использовать подзапрос.

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

Или

select EmployeeId, sum(amount)
from Sales
group by Employee
where EmployeeId in (
    select max(EmployeeId) from Employees)
27 голосов
/ 12 июня 2011

Вы не упомянули СУБД. Предполагая, что вы используете MS SQL-сервер, я обнаружил сообщение об ошибке T-SQL, которое не требует пояснений:

"Агрегат может не отображаться в ГДЕ пункт, если он не находится в подзапрос, содержащийся в предложении HAVING или список выбора, а столбец агрегированный является внешней ссылкой "

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


И пример того, что это возможно в подзапросе.

Показать всех клиентов и самый маленький заказ для тех, у кого есть 5 или более заказов (и NULL для других):

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.

Вышеописанное работает как на SQL-Server, так и на MySQL, но не возвращает ожидаемого результата. Следующий более близок. Я предполагаю, что это связано с тем, что поле customerid, GROUPed BY и используемое в соединении запрос-подзапрос, в первом случае - PRIMARY KEY внешней таблицы, а во втором - нет.

Показать все идентификаторы клиентов и количество заказов для тех, у кого есть 5 или более заказов (и NULL для других):

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 ;
9 голосов
/ 12 июня 2011

Вы не можете использовать агрегат непосредственно в предложении WHERE; для этого и нужны предложения HAVING.

Вы можете использовать подзапрос, содержащий агрегат в предложении WHERE.

7 голосов
/ 12 июня 2011

ОБНОВЛЕНО запрос:

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

Он выберет все, кроме последней строки в таблице т.

3 голосов
/ 07 декабря 2016
SELECT COUNT( * )   
FROM agents   
HAVING COUNT(*)>3;  

См. Ниже ссылку:

2 голосов
/ 31 августа 2017

Другое решение состоит в том, чтобы Переместить агрегатную функцию в Скалярную пользовательскую функцию

Создать свою функцию:

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

Используйте функцию в выражении Where

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

Ссылки:

1. 2.

Надежда помогает кому-то.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...