简体   繁体   中英

SQL Server select on aggregate function

I have a challenge regarding the use of an aggregate function in a where statement.

    SELECT [tb_users].[id_user]
      ,[name]
      ,[Title]
      ,[FirstName]
      ,[LastName]
      ,[type]
      ,sum ([tb_LockAuditTrail].[price]) as SumPrice
  FROM [SALTO_SPACE].[dbo].[tb_Users]
  join [tb_LockAuditTrail]
  on [tb_Users].[Cardcode] = [tb_LockAuditTrail].[Cardcode]

  where [type] = 1 
   group by [tb_users].[id_user]
      ,[name]
      ,[Title]
      ,[FirstName]
      ,[LastName]
      ,[type]
  order by [SumPrice] desc

This is running fine. From this dataset I want to select only the records above a certain SumPrice level. How do I do this?

I cannot use the alias SumPrice in the where statement because aliases are not allowed in where statements.

I also cannot use the aggregate SUM function in a where statement. So for now I don't see a solution other than filtering the result afterwards in an Excel sheet.

After the group by block and before the orderby block you write

HAVING sum ([tb_LockAuditTrail].[price]) > 100

Change the 100 accordingly

Even if HAVING weren't a thing, you don't have to use excel. Every SELECT creates a block of data that can be used like a table so you could wrap it all in brackets, give it an alias, and select from the query as if it were a table:

SELECT *
FROM
(
  SELECT productcategory, sum(price) as sumprice
  FROM products
  GROUP BY productcategory
) summed
WHERE
  summed.sumprice > 100

Get down with the notion that tables are only one kind of "block of data" that queries can use; you'll considerably increase your SQL querying ability if you keep in mind the fact FROM can use blocks of data from other sources such as queries and table valued functions. Here's another example:

  SELECT *
  FROM

    products p

    INNER JOIN
    (
      SELECT productcategory, sum(price) as sumprice
      FROM products
      GROUP BY productcategory
    ) sumcat
    ON p.productcategory = sumcat.productcategory

    INNER JOIN 
    (
      SELECT warehouse, count(*) as sumprice
      FROM products
      GROUP BY warehouse
    ) countwh
    ON p.warehouse = countwh.warehouse

  WHERE
    ...

You can also use the WITH command, to alias a query so you can then use it like a table:

  WITH 
    sumcat AS (
      SELECT productcategory, sum(price) as sumprice
      FROM products
      GROUP BY productcategory
    ),
    countwh as (
      SELECT warehouse, count(*) as sumprice
      FROM products
      GROUP BY warehouse
    ) 

  --now use them like tables
  SELECT *
  FROM

    products p
    INNER JOIN sumcat s ON p.productcategory = s.productcategory
    INNER JOIN countwh c ON p.warehouse = c.warehouse

This is one way how we can get every product detail but also the sum of all the prices in the category and the count of all the products in the various warehouses - perhaps pointless data but I'm demonstrating how you can use subqueries to generate blocks of data that can be joined to tables, and also each detail line can have a summary aspect too. Ordinarily you have to lose detail to generate summaries so the learning notions here are:

  • subqueries are blocks of data just like tables and can be joined just like tables
  • give everything an alias and use it
  • to get detail and summary together generate the summary and join it to the detail
  • a table can appear multiple times in a query and can be joined to itself even, so long as the two occurrences of the table have different aliases

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM