Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Having Clause

Author  Topic 

khalik
Constraint Violating Yak Guru

443 Posts

Posted - 2002-01-21 : 21:50:25

hi
small clarifying about having clause i refered but not clear... with having and where....

my query are

select count(distinct Account_ID) from bill_process having sum(Qty_usg/60)>1250

result :-- 10025


select count(distinct account_id) from bill_process where
account_id in(select distinct Account_ID from bill_process a
group by Account_ID having sum(Qty_usg/60)>1250)

result :-- 2142

i read something which says that having restrict the row return by the query but does not affect the calculation of the aggregate what does that mean

with regards
khalik



nr
SQLTeam MVY

12543 Posts

Posted - 2002-01-21 : 22:03:37
The where clause will restrict the number of rows per group.
The having clause will then work on the aggreagte function for those rows in the group to decide whether or not to return the group.

Your first query has no group so the having clause will calculate sum(Qty_usg/60)>1250 on all rows - it will then either return count(distinct Account_ID) for the whole table or return 0.
Your second query has split the result into groups on account_id.
It will then only return the count of Account_ID's for which sum(Qty_usg/60)>1250).

==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

khalik
Constraint Violating Yak Guru

443 Posts

Posted - 2002-01-21 : 22:08:33

thanks nr,
by the result i am able to understant that the first query is count of all the rows (distinct account_id)... then what is the role of having clause....

i read that if having used with out group it acts like where...
will it not work like..

select count(distinct account_id ) from bill process where
sum(Qty_usg/60)>1250

i need a query which will the desire result with out subquery..



Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2002-01-21 : 22:28:54
Have you tried it?

select count(distinct account_id)
from bill process
where sum(Qty_usg/60)>1250

should give an error.


==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

khalik
Constraint Violating Yak Guru

443 Posts

Posted - 2002-01-21 : 22:35:29


ya.. we cannot have a where with a aggregate funcation... i know

what i want to know is

A) select count(distinct account_id ) from bill process having
sum(Qty_usg/60)>1250

B) select count(distinct account_id ) from bill process where
sum(Qty_usg/60)>1250

i know a return a error but something like that...
is A and B mean the same logically....

how do i get the desire result which should have the count of distinct account_id whose usage is > 1250



Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2002-01-21 : 22:35:37
Your requirement seems to be for a count of all the Account_ids which satisfy the aggregate.
To do the aggregate test you will need to use a query which segregates accounts, the count will have to work accross those accounts so you will need something like a subquery.

select count(*)
from
(select Account_ID from bill_process
group by Account_ID having sum(Qty_usg/60)>1250)) as a

A derived table - not much different from a subquery.





==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

rrb
SQLTeam Poet Laureate

1479 Posts

Posted - 2002-01-21 : 22:38:24
nr

I'm confused but - no, it doesn't give an error - it just returns the number of records in the table, with the Having clause applied to the whole table as if it was a group -

ie if sum(Qty_usg/60)>1250 for all records in the table, then it will just return the number of records in the table.



Edited by - rrb on 01/21/2002 22:40:18
Go to Top of Page

khalik
Constraint Violating Yak Guru

443 Posts

Posted - 2002-01-21 : 22:49:42

derived table or subquery return the same result but the performances can't i get in a simple query...

if no... what does it mean by
having used with out group it acts like where...





Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2002-01-21 : 22:50:41
I was indicating the aggregate in the where clause which should give an error.
Without a group by the having clause will aggregate the whole table. The select will just return one value as it is a single group.

The having and where will do the same thing.
As the where cannot take aggregates putting the same code in the having will just restrict the rows.
With a group by clause the having can only accept the group fields without an aggregate and putting the filter in the whare clause will have the same effect.

Basically if you can put the code in a where clause you should.

In your case it can't be done easily (I think) without a subquery or similar).


==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

khalik
Constraint Violating Yak Guru

443 Posts

Posted - 2002-01-21 : 23:12:48


ok thanks for u help and info...
conclution is
its not possible to get the result without subquery or derived.. right

bye
thanks a lot
great job

Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2002-01-21 : 23:19:21
Think it might be possible with a self join.

==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

rrb
SQLTeam Poet Laureate

1479 Posts

Posted - 2002-01-21 : 23:21:53
Sorry nigel - yip you're right as always -

So khalik - why no subqueries? - If your problem is that you're doing it ADO - then create a view for your subquery ...?

I hope that when I die someone will say of me "That guy sure owed me a lot of money"
Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2002-01-21 : 23:28:24
Nope don't believe it's possible in a single query.

==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

khalik
Constraint Violating Yak Guru

443 Posts

Posted - 2002-01-21 : 23:29:44


i have a huge base and i want the result with simple query no subquery it will slow a bit and i cannot create index on this table i have several on it.. so i felt may be some other option...



Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2002-01-21 : 23:37:02
The query to get all the accounts is

select Account_ID from bill_process
group by Account_ID
having sum(Qty_usg/60)>1250)

And you will have to do all this processing to find out the accounts to count.
If as you say the count of these is about 2142 then having a subquery will not be slowing it down much - not until you get to several tens of thousands of accounts will it have much impact - but then the query above will be taking longer too.
I would assume you already have an index on Account_ID - you could make this compound with Qty_usg to speed it up a bit.
The only way I can see to have much impact would be to hold the sum in an agregate table and either update it when the main table is updated or treat this as a batch report and do the updates overnight.


==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

khalik
Constraint Violating Yak Guru

443 Posts

Posted - 2002-01-21 : 23:59:42


the result 2142 is only for few days and i have for 3 month data.. and the actual base is very big...
the query

select Account_ID from bill_process
group by Account_ID having sum(Qty_usg/60)>1250)
will give all the account but i need a single row with the count.. no problem i think when i am spending 10 hours in loading data and processing few minutes is ok....
i will compare the derived table and selfjoin and check the performances which one is better....
thanks for the help ...

thanks a lot


No problem is Big than U
Go to Top of Page

nr
SQLTeam MVY

12543 Posts

Posted - 2002-01-22 : 00:07:27
Don't think you get the point.
You will have to go through all the records to get the account aggregates so

select Account_ID from bill_process
group by Account_ID
having sum(Qty_usg/60)>1250)

is necessary.
For the server to keep a record of the account IDs and count them afterwards should not give much overhead i.e. the fact that this query is a subquery should not affect the time taken by much. Whatever you do to the query it will still have to do this processing.
The only way you can speed this up is by pre-calculating the aggregates.

You could keep a record of the last time an account is updated, keep a record of the aggregate from the query and exclude those accounts which have not been updated since the last time it was run.




==========================================
Cursors are useful if you don't know sql.
Beer is not cold and it isn't fizzy.
Go to Top of Page

khalik
Constraint Violating Yak Guru

443 Posts

Posted - 2002-01-22 : 00:25:47


ok got the point thanks

bye

Ask to your self before u ask someone
Go to Top of Page

jcelko
Esteemed SQL Purist

547 Posts

Posted - 2002-02-19 : 14:20:14
Here is how a SELECT works in SQL ... at least in theory. Real products will optimize things when they can.

a) Start in the FROM clause and build a working table from all of the joins, unions, intersections, and whatever other table constructors are there. The table expression> AS <correlation name> option allows you give a name to this working table which you then have to use for the rest of the containing query.

b) Go to the WHERE clause and remove rows that do not pass criteria; that is, that do not test to TRUE (reject UNKNOWN and FALSE). The WHERE clause is applied to the working in the FROM clause.

c) Go to the optional GROUP BY clause, make groups and reduce each group to a single row, replacing the original working table with the new grouped table. The rows of a grouped table must be group characteristics: (1) a grouping column (2) a statistic about the group (i.e. aggregate functions) (3) a function or (4) an expression made up of the those three items.

d) Go to the optional HAVING clause and apply it against the grouped working table; if there was no GROUP BY clause, treat the entire table as one group.

e) Go to the SELECT clause and construct the expressions in the list. This means that the scalar subqueries, function calls and expressions in the SELECT are done after all the other clauses are done. The AS operator can give a name to expressions in the SELECT list, too. These new names come into existence all at once, but after the WHERE clause, GROUP BY clause and HAVING clause has been executed; you cannot use them in the SELECT list or the WHERE clause for that reason.

If there is a SELECT DISTINCT, then redundant duplicate rows are removed. For purposes of defining a duplicate row, NULLs are treated as matching (just like in the GROUP BY).

f) Nested query expressions follow the usual scoping rules you would expect from a block structured language like C, Pascal, Algol, etc. Namely, the innermost queries can reference columns and tables in the queries in which they are contained.


--CELKO--
Joe Celko, SQL Guru
Go to Top of Page
   

- Advertisement -