Forum Moderators: open
In the query above, the logintable has many records, even for the "max" command, so my count(id) is skewed based on the the number of times the user is in the logintable.
Is there a better way to write this query? I thought about a subselect in the Select clause, but couldn't figure that one out, given the outer join nature.
Thanks.
The count is the number of students for that one schcode.
The schemas are fairly large so I'll summarize:
users:
user
pwd
schcode
name
head
schoolinfo:
schcode
school
auth
students:
id
schcode
logintable:
user
users > logintable is one to many
schoolinfo > users is one to many
schoolinfo > students is one to many
Hope that clears it up.
If thats it, I would use inner joins and just group by school, then count isnt affected by the number of rows in login table
FROM ((schoolinfo INNER JOIN students ON schoolinfo.schcode = students.schcode) INNER JOIN users ON schoolinfo.schcode = users.schcode ) INNER JOIN logintable ON users.user = logininfo.user
group by schoolinfo.school
order by school, logindate desc
The max(empty_set) is a problem. Rather than use expesive cartesian product or suqueries,I would be tempted solve it with a an insert trigger on users, to insert into logintable a default "01-01-1901" whenver a user is created.
You could then create a view that restricts using "where logindate >01-01-1901", or substitutes it for 'None' using a CASE statement in the query, or just handle it in the application.
Thats one way, not a great one actually :) Im sure there are other ways.
Users is inner joined with logins as if there are no users there cant be any logins so you just get an enmpty set, not null.
That join is then is then right outer joined to schools so that you still get a row for every school. So the empty set from the first query is then casted by the db server, in SQL2K this gives NUll.
Schools is then outer joined on the other side to students,again to get a row for every school.
Just group by School as you want 1 row per schoolID.
Users INNER JOIN
Logins ON Users.UserID = Logins.UserID
RIGHT OUTER JOIN
Schools ON dbo.Users.SchoolID = Schools.SchoolID LEFT OUTER JOIN
Students ON Schools.SchoolID = Students.SchoolID
GROUP BY Schools.SchoolID
You can test each bit and it simplifies the main query.
CREATE VIEW StudentCount
AS
SELECT School.SchoolID, COUNT(Students.StudentID) AS Students
FROM School LEFT OUTER JOIN
Students ON School.SchoolID = Students.SchoolID
GROUP BY School.SchoolID
CREATE VIEW LoginDates
AS
SELECT MAX(Logins.LoginDate) AS MaxLoginDate, Users.UserID, Users.SchoolID
FROM Users INNER JOIN Logins ON Users.UserID = Logins.UserID
GROUP BY Users.UserID, Users.SchoolID
CREATE VIEW MasterQuery
AS
SELECT StudentCount.SchoolID, StudentCount.Students, LoginDates.MaxLoginDate AS MaxLoginDate
FROM LoginDates RIGHT OUTER JOIN
StudentCount ON LoginDates.SchoolID = StudentCount.SchoolID