Thread: Getting matching and non-matching results (long)

Getting matching and non-matching results (long)

From
Roberto Mello
Date:
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


Re: Getting matching and non-matching results (long)

From
Stephan Szabo
Date:
> 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?



Re: Getting matching and non-matching results (long)

From
Roberto Mello
Date:
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...


Re: Getting matching and non-matching results (long)

From
Stephan Szabo
Date:
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;