How do I select mothers in the table that have children of all the listed genders? (implementing RA Division in SQL) - sql

I have a table (person) with the following columns:
name, gender, mother
and I need to extract the names of the mothers who have a baby of every gender. I'm not allowed to assume that gender is limited to just M and F.
I can do SELECT DISTINCT person.gender FROM person to get a list of all genders present in the table.
I also created a table with all the names of the mothers and their child's gender as the two columns.
The problem is, I have no idea how to check if a mother has had a child of all respective genders in the table. How can I implement this?
Edit: How I achieved my final solution can be found below, thank you all for your answers! I have also updated the title to help others find it.

Group the mothers' records together, and in each group count how many distinct genders there are.
SELECT
mother
FROM
person
GROUP BY
mother
HAVING
COUNT(DISTINCT gender) = (SELECT COUNT(DISTINCT gender) FROM person)

I ultimately approached the issue the same as #MatBailie but found it useful to include the COUNT in the final query as well. You basically need two things to make this type of query work. 1) A collection of distinct mothers, 2) The number of distinct genders. A GROUP BY and an aggregate subquery works nicely here.
SELECT COUNT(DISTINCT gender) AS genderCount, mother FROM person
GROUP BY mother
HAVING genderCount = (SELECT COUNT(DISTINCT gender) from person);

In the end I implemented the relational algebra division method into SQL using various EXCEPT and IN conditions. Relational algebra division works great when you have two columns, where some kind of label (e.g. a name) is connected to some type (e.g. gender), and you wish to find if a specific label is linked to all types that are specified in another, separate table.
In my case the list of labels were the names of the mothers, and their associated type was the gender of their child. Using the SELECT statement I created in my question post, this gave me a list of genders where each mother must have for my query. This was my "type" table, that all the mothers had to link to.
This is how I got the answer to my question in the end.
A nice, detailed guide on how to implement it is here:
https://www.geeksforgeeks.org/sql-division/
The other answers do also work and are much simpler, but this solution feels more general and I think it should be shared!

Related

If I have multiple values in a column, how can I count it in SQL?

Let me illustrate this:
Student_ID
Course
StudentID1
CourseA
StudentID2
CourseB
StudentID3
CourseA CourseB
There is an existing table that has data that looks like the one above (Not exactly Student & Course, this is more for illustration purpose) and my job is to do a count of how many students for each course. The table is very huge and I do not know how many and what are the courses are out there (Easily in thousands), so wonder if there is a way I can get a list of all these courses and their counts through SQL?
The current method that my team did is SELECT DISTINCT COURSE, COUNT(STUDENT_ID) FROM TABLE GROUP BY COURSE, but this does not work because it treats "CourseA CourseB" as its own.
There are some other columns in this table that I might need to do a SUM as well.
Appreciate any advice on this, thanks!
you could use below to find number of students for each course:
select course, count(*) as no_of_students
from table
group by course;

Count unique values in Access query

I'm pretty much an Access n00b, but I've built a basic database for a friend's school to keep track of students seeing the counselling team. They're all pretty happy with it, but they've asked if it's possible to quickly see how many students each counselor is seeing.
I have tables set up for staff, students, and case notes, and I thought it would be easy to create a query that does this, but I cant get it to work; it keeps returning the number of case notes per staff member, rather than the students:
Query right now. Staff #7 has seen one student twice.
What I'd like it to do is tell me how many students each counselor is seeing, based on the case notes they've entered.
I'm really hoping for a solution I can implement in design view, rather than SQL.
You can DL the database if you want to look at it:https://drive.google.com/file/d/0B0RvbnEcKEagZldJMDZkZmkybkk/view?usp=sharing
(It's all dummy data)
Thanks in advance for any guidance you can offer me.
I was going to say, "count distinct," but apparently that's not a thing in Access.
Instead, you'll need to run two queries that are the equivalent of
select StaffID, FirstName, LastName, count(*)
from (
select distinct StaffID, FirstName, LastName, Student
from TblStaff stf join TblCaseNote nte on nte.Staff = stf.StaffID
) foo
group by StaffID, FirstName, LastName
The first query should have StaffID, FirstName, LastName, and Student, each set to Group By.
Then create another query that has the first as its source and Group By all columns except Student, which you should count.

Retrieving duplicate and original rows from a table using sql query

Say I have a student table with the following fields - student id, student name, age, gender, marks, class.Assume that due to some error, there are multiple entries corresponding to each student. My requirement is to identify the duplicate rows in the table and the filter criterion is the student name and the class.But in the query result, in addition to identifying the duplicate records, I also need to find the original student detail which got duplicated. Is there any method to do this. I went through this answer: SQL: How to find duplicates based on two fields?. But here it only specifies how to find the duplicate rows and not a means to identify the actual row that was duplicated. Kindly throw some light on the possible solution. Thanks.
First of all: if the columns you've listed are all in the same table, it looks like your database structure could use some normalization.
In terms of your question: I'm assuming your StudentID field is a database generated, primary key and so has not been duplicated. (If this is not the case, I think you have bigger problems than just duplicates).
I'm also assuming the duplicate row has a higher value for StudentID than the original row.
I think the following should work (Note: I haven't created a table to verify this so it might not be perfect straight away. If it doesn't it should be fairly close)
select dup.StudentID as DuplicateStudentID
dup.StudentName, dup.Age, dup.Gender, dup.Marks, dup.Class,
orig.StudentID as OriginalStudentId
from StudentTable dup
inner join (
-- Find first student record for each unique combination
select Min(StudentId) as StudentID, StudentName, Age, Gender, Marks, Class
from StudentTable t
group by StudentName, Age, Gender, Marks, Class
) orig on dup.StudentName = orig.StudenName
and dup.Age = orig.Age
and dup.Gender = orig.Gender
and dup.Marks = orig.Marks
and dup.Class = orig.Class
and dup.StudentID > orig.StudentID -- Don't identify the original record as a duplicate

Retrieve count of related records

I currently have two tables in my data source that I'm referencing in this instance.
Firstly, to explain the context, I have a windows form program in VB.NET (Visual Studio 2013).
In the first table Trainer, I have the following fields : ID, First Name, Surname, Contact, Class.
In the second table Member, I have the following fields : ID, First Name, Surname, Contact, Type, TrainerID.
I have enforced referential integrity between the two tables using Trainer.ID as PK and Member.TrainerID as FK with a 1:m relationship. I'm trying to retrieve the count of related records, to the specified ID of the trainer. I want to retrieve the count of related records. So, for example on the form I click Search and provide a trainer ID, I'd like to return the amount of customers he/she has belonging to them.
I need that, so that I can work out their salary based on commission + base amount.
I've looked around a lot, read up a lot but I just can't seem to get it. Any help whatsoever will be appreciated.
If you have the trainer id, can't you just do:
select count(*) as cnt
from member m
where m.trainerid = #TheTrainerId;
select count(m.id) as count_members
from trainer t
left join member m on m.trainerid = t.id
where t.surname = 'watson'

Oracle SQL, not exist and count

I am currently stuck with my assignment. I am not trying to be lazy but I can't seems to find a solution and my teacher guided me by saying to use not exist or count.
I need to find patients name who have been treated by all the doctors. Currently I am just using plain intersect SQL command for each doctor name (In the question, there are only 3 doctors) but of course its not realistic when there are 100's of doctors name.
The scheme is as below.
Patient (PatientID, FamilyName, GivenName)
Account (ProviderNo, PatientID)
Doctor (ProviderNo, Name)
Any help would be greatly appreciated.
I won't provide you the exact Query.
But here is the psuedo code:
group PatientId in Account where its distinct ProviderNo count should be
equal to no. of Doctors