Warning

 

Close
Confirm Action

Are you sure you wish to do this?

Cancel Confirm
AR15.COM
1/25/2011 2:22:37 PM EDT
This works:

SELECT AVG(QuantityOnHand)

  AS AVGquantity FROM INVENTORY

  WHERE Warehouse IN

     (SELECT Warehouse
        FROM WAREHOUSE
        WHERE Manager='Smith');


But this doesnt:

SELECT Warehouse, AVG(QuantityOnHand)

  AS AVGquantity FROM INVENTORY

  WHERE Warehouse IN

     (SELECT Warehouse
        FROM WAREHOUSE
        WHERE Manager='Smith');

Access gives me error "You tried to execute a query that does not include the specified expression 'Warehouse' as part of an aggregate function"  I dont understand why its wrong as Warehouse is a column title in Inventory

1/25/2011 2:28:32 PM EDT
[#1]
I would say it is because warehouse is a table.  rather than a field in the table containing data.  But it has been a long time since I've even thought about SQL.
1/25/2011 2:29:34 PM EDT
[#2]
Yeah I can see it's wrong, give me a sec to give an explanation.
1/25/2011 2:30:58 PM EDT
[#3]
Quoted:
I would say it is because warehouse is a table.  rather than a field in the table containing data.  But it has been a long time since I've even thought about SQL.


Well there is a table called WAREHOUSE, but the INVENTORY table has a column titled 'Warehouse'

There is an almost identical example of successfully doing this in the book, instead of using AVG like Im doing it uses COUNT(*)
1/25/2011 2:33:36 PM EDT
[#4]
The average function is an aggregate function, so it spans many rows.  You get the average of all the warehouses that are managed by Smith.  And you're going to get it in one row.

You cannot select all of the Warehouse names (or IDs) in one field.

If you're looking to get averages by manager, link them relationally and select the warehouse manager's name, and the average, and include a GROUP BY clause.
1/25/2011 3:10:56 PM EDT
[#5]



Quoted:


The average function is an aggregate function, so it spans many rows.  You get the average of all the warehouses that are managed by Smith.  And you're going to get it in one row.



You cannot select all of the Warehouse names (or IDs) in one field.



If you're looking to get averages by manager, link them relationally and select the warehouse manager's name, and the average, and include a GROUP BY clause.


Yep pretty much exactly what he said, pretty much and time you use a function like sum or avg you are going to have to include a group by statement if you are selecting any columns other than the field you are performing the calculation on.



 
1/25/2011 3:17:10 PM EDT
[#6]
This should work



SELECT
    Warehouse,
    AVG(QuantityOnHand) AS AVGquantity
FROM INVENTORY
WHERE Warehouse IN
                     (SELECT Warehouse
                      FROM WAREHOUSE
                      WHERE Manager='Smith')
GROUP BY
   Warehouse;


I would probably go a step further and use a join on the Inventory and warehouse tables to get rid of the sub select.
1/25/2011 3:21:47 PM EDT
[#7]
I haven't done SQL in > 10 years.

I don't miss it.
1/25/2011 3:30:47 PM EDT
[#8]
Quoted:
This should work


SELECT      Warehouse,      AVG(QuantityOnHand) AS AVGquantity FROM INVENTORYWHERE Warehouse IN                      (SELECT Warehouse                       FROM WAREHOUSE                       WHERE Manager='Smith')GROUP BY    Warehouse;


I would probably go a step further and use a join on the Inventory and warehouse tables to get rid of the sub select.


thats the answer, you need the 'group by' since you are 'aggregating' (averaging) QuandityOnHand for each warehouse.

select
i.warehouse
,avg(i.QuantityOnHand)

from inventory i
join warehouse w on w.warehouse on i.warehouse
                                                   and w.manager = 'Smith'
group by i.warehouse
order by  i.warehouse

i think thats how you might do it with a join. however the optimizer is likely to do the same thing

ETA, i assume your db isnt case sensitive.
1/25/2011 4:01:24 PM EDT
[#9]
Guys, there's only one row that's going to be returned.  There's nothing really to group by, because really he's grouping by the manager name.  He's looking for the average of that group of warehouses.
1/25/2011 4:33:27 PM EDT
[#10]
right, and sort of

Only one row and 1 column is being returned for the query that works- Smith only has 1 Warehouse (Chicago) and what I need returned is 1 row with 2 colums , Chicago and 217 which is the average qty for all items stored in Smiths warehouse in Chicago
1/25/2011 4:35:49 PM EDT
[#11]
Quoted:
This works:

SELECT AVG(QuantityOnHand)

  AS AVGquantity FROM INVENTORY

  WHERE Warehouse IN

     (SELECT Warehouse
        FROM WAREHOUSE
        WHERE Manager='Smith');


But this doesnt:

SELECT Warehouse, AVG(QuantityOnHand)

  AS AVGquantity FROM INVENTORY

  WHERE Warehouse IN

     (SELECT Warehouse
        FROM WAREHOUSE
        WHERE Manager='Smith');

Access gives me error "You tried to execute a query that does not include the specified expression 'Warehouse' as part of an aggregate function"  I dont understand why its wrong as Warehouse is a column title in Inventory



you are missing the group by in the second query

I would write it as follows:

select i.Warehouse,
         avg(QuantityOnHand)  AS AVGquantity
from INVENTORY i inner join WAREHOUSE w on i.warehouse = w.warehouse
where w.manager = 'Smith'
group by i.Warehouse
1/25/2011 4:36:10 PM EDT
[#12]
Quoted:
right, and sort of

Only one row and 1 column is being returned for the query that works- Smith only has 1 Warehouse (Chicago) and what I need returned is 1 row with 2 colums , Chicago and 217 which is the average qty for all items stored in Smiths warehouse in Chicago

That's not going to happen.  Because there can be as many warehouses for Smith as you want, and the SQL engine knows this.  The average quantity is not necessarily unique to "Chicago".

Change it up so you are selecting from both tables, and don't use the sub-query.  In the WHERE clause, relate the two with the Warehouse as the foreign key.  Then group by warehouse and constrain the manager to be Smith.
1/25/2011 4:41:24 PM EDT
[#13]
Quoted:
Guys, there's only one row that's going to be returned.  There's nothing really to group by, because really he's grouping by the manager name.  He's looking for the average of that group of warehouses.


wrong.  he is grouping by warehouse.  when you have an aggregate function in the select clause all non aggregates must be in a group by clause
1/25/2011 4:44:47 PM EDT
[#14]
Quoted:
Quoted:
Guys, there's only one row that's going to be returned.  There's nothing really to group by, because really he's grouping by the manager name.  He's looking for the average of that group of warehouses.


wrong.  he is grouping by warehouse.  when you have an aggregate function in the select clause all non aggregates must be in a group by clause

I relooked at it.  I stand corrected. What you're saying makes more sense.
1/25/2011 5:04:34 PM EDT
[#15]



Quoted:



Quoted:

Guys, there's only one row that's going to be returned.  There's nothing really to group by, because really he's grouping by the manager name.  He's looking for the average of that group of warehouses.




wrong.  he is grouping by warehouse.  when you have an aggregate function in the select clause all non aggregates must be in a group by clause


I'm no SQL expert, but I believe that is correct. He needs a group by clause.



 
1/26/2011 1:47:26 PM EDT
[#16]
OK I see how GROUP BY works.   nifty.

someone said something about doing it with a join, if I wanted to do the same thing with a join instead of using a subquery then this kinda works:

SELECT INVENTORY.Warehouse, Avg(INVENTORY.QuantityOnHand) AS AVGquantity
FROM INVENTORY, WAREHOUSE
GROUP BY INVENTORY.Warehouse

but I get all the Warehouses, not just Smith's warehouse.  If I try:

SELECT INVENTORY.Warehouse, Avg(INVENTORY.QuantityOnHand) AS AVGquantity
FROM INVENTORY, WAREHOUSE
GROUP BY INVENTORY.Warehouse
HAVING WAREHOUSE.Manager='Smith';

I get another aggregate function error


ETA just figured it out:

SELECT INVENTORY.Warehouse, Avg(INVENTORY.QuantityOnHand) AS AVGquantity
FROM INVENTORY, WAREHOUSE
WHERE INVENTORY.Warehouse=WAREHOUSE.Warehouse and WAREHOUSE.Manager='Smith'
GROUP BY INVENTORY.Warehouse;

duh.  thanks guys