November 14, 2005 at 2:02 am
Dear all,
I now have a problem for the my sub-query, my SQL code is as below:-
SELECT COUNT(t1.StudentID), COUNT(t2.StudentID)
FROM
(SELECT StudentID
FROM Attendance
WHERE ClassId=1 and Month(Date)=11 and status=0
GROUP BY studentID
HAVING COUNT(studentid)<3 ) T1,
(SELECT StudentID
FROM Attendance
WHERE ClassId=1 and MONTH(Date)=11 and status=0
GROUP BY studentID
HAVING COUNT(studentid)>2 AND COUNT(studentid)<6 ) T2
The problem here is that the results are 0,0 for both counts. This is not what i was expecting, the answer should be 3 for t1's count and 0 for t2's count. However, if i run the SQL like below:-
SELECT COUNT(t1.StudentID)
FROM
(SELECT StudentID
FROM Attendance
WHERE ClassId=1 and Month(Date)=11 and status=0
GROUP BY studentID
HAVING COUNT(studentid)<3 ) T1
The count returns 3 as expected but i just don't get it, why does the second SQL query works while the first one does not? Please help me out here and do point out if I am doing anything wrong.
Thanks.
November 14, 2005 at 2:15 am
If you put the COUNTs in the subqueries, I think that this will work:
SELECT t1.TotalRows, t2.TotalRows FROM
(SELECT count(StudentID) TotalRows
FROM Attendance
WHERE ClassId=1 and Month(Date)=11 and status=0
GROUP BY studentID
HAVING COUNT(studentid)<3 ) T1,
...
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
November 14, 2005 at 2:23 am
Hi there Phil,
I tried out your suggestion and it won't work. Besides that, it won't give me the results I want because the having clause filters whatever is returned by the SELECT query (if I am right).
Anybody have any idea why this my problem is happening, or any other solution?
Thanks.
November 14, 2005 at 2:58 am
OK - I see now what you're trying to do.
One idea I've had, which I've not tested, is for you to have a single subquery containing two counts
select studentid, count1, count2 (this is pseudo-code)
and change your WHERE clause to include the data from both your subqueries:
HAVING COUNT(studentid) < 6
then use a CASE statement to assign the count to either count1 or count2. Does that make sense?
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
November 14, 2005 at 3:12 am
I get what you are trying to do but unfortunately I am not very good in SQL Server's syntax and I have no idea on how to put a CASE statement after my selection.
Could you be kind enough to show me how? Or provide a sample on how to do it?
Thanks.
November 14, 2005 at 3:42 am
OK, here's an example. Try running against the Northwind database.
select employeeid,
Count1 = (
case
when Count(EmployeeID) < 100 then Count(EmployeeID)
else 0
end
),
Count2 = (
case
when Count(EmployeeID) >= 100 then Count(EmployeeID)
else 0
end
)
from orders
group by EmployeeID
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
November 14, 2005 at 4:14 am
I see where we are heading here, and i have tried out the code you gave on the NorthWind database. Now I want to sum COUNT1 and COUNT2, but when i put SUM( COUNT1=(....) ) I get an error that says there is a syntax error near '='.
How would I go about to sum them up? Thanks for the prompt reply, really appreciate your help and your time spent.
November 14, 2005 at 4:38 am
Sticking with Northwind, is this roughly where you're heading?
select sum(t1.Count1), sum(t1.Count2) from
(select employeeid,
Count1 = (
case
when Count(EmployeeID) < 100 then Count(EmployeeID)
else 0
end
),
Count2 = (
case
when Count(EmployeeID) >= 100 then Count(EmployeeID)
else 0
end
)
from orders
group by EmployeeID) t1
The absence of evidence is not evidence of absence.
Martin Rees
You can lead a horse to water, but a pencil must be lead.
Stan Laurel
November 14, 2005 at 5:52 am
Alright, I see where my error was when I adapted the code to fit my needs. It's all fine now and everything is working as it should
Thanks Phil, you're a real life-saver. Thanks again.
November 15, 2005 at 1:42 pm
Been playing around with the SQL above.
The reason the original SQL returns 0, 0 is because hidden in the query is a cross join where one of the queries returns no rows. A cross join multiplies up the number of rows; if one query is empty, the resultset is empty too.
Using an adaptation of the original query to Northwind:
SELECT COUNT(t1.EmployeeID), COUNT(t2.EmployeeID)
FROM
(SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(EmployeeID)<100 ) T1, -- returns 5 rows
(SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(EmployeeID)>100 ) T2 -- returns 4 rows
returns 20, 20
-- No claims this is 'better' than the query above
-- simply an illustration of another way to
-- remove the fur from a feline
Select (Select count(*)from (select employeeid from Orders group by employeeId having count(*)<100) t1) countT1,
(Select count(*)from (select employeeid from Orders group by employeeId having count(*)>100) t1) countT2
This query returns 5, 4
Regards
Otto
Otto Schreibke
The future is a foreign country, they do things differently there.
(Stolen from Arthur C Clarke)
November 16, 2005 at 1:29 am
The problem here is that the results are 0,0 for both counts. |
IT mean 3 * 0 = 0
SELECT COUNT(t2.StudentID)
FROM
(SELECT StudentID
FROM Attendance
WHERE ClassId=1 and MONTH(Date)=11 and status=0
GROUP BY studentID
HAVING COUNT(studentid)>2 AND COUNT(studentid)<6 ) T2
return 0
November 16, 2005 at 7:52 am
Let me try to explain what's going on in a little more detail.
Using the northwind database query
SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
returns 9 rows (Employee ids 1, 2, ... 8, 9)
Query
SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(EmployeeID)<100
returns 5 rows (Employee ids 2, 5, 6, 7 and 9)
Query
SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(EmployeeID)>100
returns 4 rows (Employee ids 1, 3, 4 and 8)
Query
SELECT COUNT(t1.EmployeeID), COUNT(t2.EmployeeID)
FROM
(SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(EmployeeID)<100 ) T1, -- returns 5 rows
(SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(EmployeeID)>100 ) T2 -- returns 4 rows
returns 20 rows; the pairs
2, 1
5, 1
6, 1
7, 1
9, 1
2, 3
5, 3
6, 3
7, 3
9, 3
2, 4
5, 4
6, 4
7, 4
9, 4
2, 8
5, 8
6, 8
7, 8
9, 8
because in the cross join every row in the first resultset is combined with every row in the second.
the using the count clause will return 20, 20 as there are 20 non-null values for each count.
If you change the selections to
SELECT *
FROM
(SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(EmployeeID)<1000 ) T1, -- returns 9 rows
(SELECT EmployeeID
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(EmployeeID)>1000 ) T2 -- returns 0 rows
In this case, the rowset resulting from combining the two subqueries is empty, and the counts will be 0, 0.
In summary:
1. the query contains a cross join - (think this is also called a cartesian join), therefore the resulting rowset contains a number of rows which is the product of the number of rows in the subqueries. If one subquery is empty, the resultset will also be empty.
2. the count clause operates on all the rows in the combined resultsset. it doesn't take account of the different number of rows in the subqueries; it operates on the combined rowset.
Hope this helps explain what's going on.
Regards
Otto
Otto Schreibke
The future is a foreign country, they do things differently there.
(Stolen from Arthur C Clarke)
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply