Thread: Getting matching and non-matching results (long)
Hi all, I'me needing some help with a query on a non-profit project I'm involved with. I appreciate any help. It's a system to keep track of incidents in schools, including drug offenses. Each incident can have zero or more drug incidents related with it, and each of these incidents can have 1 or more drugs involved. To complicate things a bit, I need a query that will return these incidents by different drugs and grades. What I need is to find a count of drug incidents grouped by drugs and grade. Here's the table stucture (summarized): create table sds_grades (grade_id integer constraint sds_grades_pk primary key,grade_name varchar(100) ); create table sds_offenders (offender_id integer constraint sds_offenders_pk primary key,participant_id integer constraintsds_offenders_part_id_fk references sds_participants,incident_id integer constraint sds_offenders_incident_id_fkreferences sds_incidents on delete cascade,unknown_count integer,grade_id integer constraintsds_offenders_grade_id_fk references sds_grades, ... ); create table sds_drugs (drug_id integer constraint sds_drugs_pk primary key,drug_name varchar(200),offense_precedenceinteger,sort_key integer ); create table sds_drug_offenses (drug_offense_id integer constraint sds_drug_offenses_pk primary key,offender_id integerconstraint sds_drug_offender_id_fk references sds_offenders on delete cascade,drug_id integer constraint sds_drug_id_fkreferences sds_drugs,drug_violation_id integer constraint sds_drug_violation_id_fk references sds_drug_violations,drug_descriptionvarchar(200) ); The query I came up with so far was this: SELECT COUNT(incident_id), drug_name, grade_name FROM sds_offenders o, sds_drugs d, sds_drug_offenses do, sds_grades g WHERE o.drug_p = 't' AND o.offender_id = do.offender_id AND d.drug_id = do.drug_id GROUP BY drug_name, grade_name, d.sort_key ORDER BY d.sort_key This gives me wrong results (if there's one incident in a certain grade, it'll show the same result for all grades, even though the other grades have no incidents). It's a work in progress just to give you an idea. I'm thinking I need an OUTER JOIN somewhere there, but my attempts have not been successful. Any pointers? Thanks in advance. -Roberto -- +----| http://fslc.usu.edu USU Free Software & GNU/Linux Club |------+ Roberto Mello - Computer Science, USU - http://www.brasileiro.net http://www.sdl.usu.edu - Space Dynamics Lab, Developer * * * <- Tribbles <- Cloaked tribbles
> create table sds_grades ( > grade_id integer > constraint sds_grades_pk primary key, > grade_name varchar(100) > ); > > create table sds_offenders ( > offender_id integer > constraint sds_offenders_pk primary key, > participant_id integer > constraint sds_offenders_part_id_fk references sds_participants, > incident_id integer > constraint sds_offenders_incident_id_fk references sds_incidents on delete cascade, > unknown_count integer, > grade_id integer > constraint sds_offenders_grade_id_fk references sds_grades, > ... > ); > > SELECT COUNT(incident_id), drug_name, grade_name > FROM sds_offenders o, sds_drugs d, sds_drug_offenses do, sds_grades g > WHERE o.drug_p = 't' > AND o.offender_id = do.offender_id > AND d.drug_id = do.drug_id > GROUP BY drug_name, grade_name, d.sort_key > ORDER BY d.sort_key I think you need a g.gradeid=o.gradeid in the where clause as well to constrain g to the grade for which the offender belonged, right?
On Wed, Dec 05, 2001 at 01:07:20PM -0800, Stephan Szabo wrote: > > > > SELECT COUNT(incident_id), drug_name, grade_name > > FROM sds_offenders o, sds_drugs d, sds_drug_offenses do, sds_grades g > > WHERE o.drug_p = 't' > > AND o.offender_id = do.offender_id > > AND d.drug_id = do.drug_id > > GROUP BY drug_name, grade_name, d.sort_key > > ORDER BY d.sort_key > > I think you need a > g.gradeid=o.gradeid > in the where clause as well to constrain g to > the grade for which the offender belonged, right? Yes, I figured this mistake minutes after sending the message to the list. The problem is that with g.grade_id = o.grade_id there it gives me _only_ the grades that have incidents in them, instead of _all_ the grades with 0's for those without incidents. -Roberto -- +----| http://fslc.usu.edu USU Free Software & GNU/Linux Club |------+ Roberto Mello - Computer Science, USU - http://www.brasileiro.net http://www.sdl.usu.edu - Space Dynamics Lab, Developer "Carrier detected." Go to the dentist...
On Wed, 5 Dec 2001, Roberto Mello wrote: > On Wed, Dec 05, 2001 at 01:07:20PM -0800, Stephan Szabo wrote: > > > > > > SELECT COUNT(incident_id), drug_name, grade_name > > > FROM sds_offenders o, sds_drugs d, sds_drug_offenses do, sds_grades g > > > WHERE o.drug_p = 't' > > > AND o.offender_id = do.offender_id > > > AND d.drug_id = do.drug_id > > > GROUP BY drug_name, grade_name, d.sort_key > > > ORDER BY d.sort_key > > > > I think you need a > > g.gradeid=o.gradeid > > in the where clause as well to constrain g to > > the grade for which the offender belonged, right? > > Yes, I figured this mistake minutes after sending the message to the list. > The problem is that with g.grade_id = o.grade_id there it gives me _only_ > the grades that have incidents in them, instead of _all_ the grades with > 0's for those without incidents. Right, then you will want an outer join, probably something like: select count(incident_id), drug_name, grade_name from ((sds_offenders o inner join sds_drug_offenses dro using (offender_id)) inner join sds_drugs d using (drug_id)) right joinsds_grades using (grade_id) where o.drug_p='t' group by drug_name, grade_name, d.sort_key order by d.sort_key;