Count unique values in Access query - sql

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.

Related

How do I select mothers in the table that have children of all the listed genders? (implementing RA Division in 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!

Grouping other fields by common email

I'd appreciate any assistance people could provide with this one. I've tried to follow a couple of other posts (GROUP BY to combine/concat a column), but when I do this, it combines everything.
I have a table in SQL that holds contact data. Some contacts in the database have the same email address, particularly admin#, accounts#, etc. We also have a list of contact preferences for each contact: Emergency Contact, Accounts, WHS, etc. I'm trying to select the results of the table, but only one row per email address.
My data looks like this:
However, I'd like it to group the rows together that have the same email address (I don't care about the names). I'd also like it to look at the contact preference fields and if even one of the joined fields had a yes, show a Y, otherwise show a N - see below example
As I mentioned, all my tests have been unsuccessful I'm afraid, so I would appreciate any assistance that you can provide.
You can use the following:
;WITH selected as (
select min(ContactID) as ContactID, Mail, max(EmergencyContact) as EmergencyContact,
max(AccountsCon) as AccountsCon, max(WHSContact) as WHSContact
from t
GROUP BY Mail
)
select t.ContactID, t.BusinessID, t.BusinessName, t. FirstName, t.LastName, t.Position, t.Mail, s.EmergencyContact, s.AccountsCon, s.WHSContact
from selected as s
inner join t as t ON t.ContactID = s.ContactID
This way you get the contactid, businessid, businessname, firstname, lastname and position from the first record found with each email and the last 3 columns you get using max (taking advantage that Y is greater than N, so if there is at least one Y it will get Y).
I think you can just use aggregation:
select businessid, businessname, max(firstname),
max(lastname), max(position),
email,
max(emergencycontact),
max(accountscor),
max(whcontact)
from t
group by businessid, businessname, email;

Query with 2 filters in Access

I'm doing work experience where I've created a database of past students in Microsoft Access 2007.
I have problem with creating a query to filter students who have done Introduction Course but nothing else. I guess I need 2 filters.
I have Two tables: Customers and Courses with an one to many relationship: each customer/student can attend one or more courses.
So there are students who did one or more than one courses. I have 111 students who did Introduction course. But some of them did Intermediate course as well or both Intermediate course and Advanced course as well.
I need to filter students who have done Introduction course but nothing else;
And who have done both Introduction course and Intermediate course but nothing else;
I'm struggling to separate those students
At the moment my SQL statement looks like this:
SELECT Customers.FirstName, Customers.Surname, Customers.Email, Courses.CourseName, Courses.CourseDate, Customers.CustID
FROM Customers INNER JOIN Courses ON Customers.CustID = Courses.CustID
WHERE (((Courses.CourseName) Like "Intro?*"))
ORDER BY Customers.FirstName;
The current result is 111 students. But more than half of them did other courses as well(if you count manually).
I need to filter students who have done Introduction course only but nothing else (the list of students - their details, who did not do any other course, just Introduction);
I want to create a query to find out who have done Introduction course but nothing else;
Second query is to find out who have done "Introduction course and Intermediate course but nothing else" .
Courses Table
CourseID
CourseName
CourseDate
CustID
Notes
There is a list of other courses in the "Courses Table"
Advanced
Airbrush
Bridal
Hair
Intermediate
Introduction
Refreshner
Customer Table
CustID
FirstName
Surname
Email
Phone
Address1
Address2
Address3
DateOfBirth
Extra info
That's my problem. I still can not figure out how to do that students with other courses shall not be part of the result???
This is the code I came up with to find out Who Did more than Introduction course:
SELECT Customers.FirstName, Customers.Surname, Customers.Email, Count(Courses.CourseName) AS CountOfCourseName, Courses.CustID
FROM Customers INNER JOIN Courses ON Customers.CustID = Courses.CustID
GROUP BY Customers.FirstName, Customers.Surname, Customers.Email, Courses.CustID
HAVING (((Count(Courses.CourseName))>1));
Now I need to figure out how to hide them but instead to display who did only Introduction course and nothing else (?).
Generally I suggest you read about sub-queries and combining queries.
In your attempts you miss the "but not like" dependency between customers and courses.
I tried the following in PostgreSQL, so I don't know if this adapted version works in Access.
It also might not be the most efficient solution.
SELECT FirstName, Surname, Email, CourseName, CourseDate, Customers.CustID
FROM Customers INNER JOIN Courses ON Customers.CustID = Courses.CustID
WHERE CourseName LIKE "Intro*" AND Courses.CustID NOT IN
(SELECT CustID
FROM Courses
WHERE CourseName IN ("Advanced", "Airbrush", "Bridal", "Hair", "Intermediate", "Refreshner"))
ORDER BY FirstName;
For your second query you have switch "Introduction" with "Intermediate". That will give you all customers who only attended the Intermediate course. Then you have to use UNION, to combine this query with your first one (SELECT [A] UNION SELECT [B]). Of course the ORDER BY FirstName in the middle has to be removed, as well as the semicolon in the middle. This will get you all customers who attended the Introduction and Intermediate course, but nothing else. Again, this might not be the most efficient solution.

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

Beginner SQL Developer questions

So I am currently in a DBMS class, and we are doing a section on SQL. It basically consists of me creating a database for 5 guests staying at a hotel. There are 8 tables with information (Tables listed below). I currently have all the info for the tables entered and working (not included below), but am stuck on a few queries that we are required to write for the assignment.
The query that I am stuck on: Don't even really know where to start on this one.
Name of guests who have incurred charges for golf and dinner in the
same itinerary.
Any help would be appreciated. I know I didn't include the actual data used for each table below, so let me know if you need any other information that may help to write the queries. Any help is appreciated, thanks.
1.GUEST (GUESTID, LASTNAME, FIRSTNAME, MIDINIT, STRADDR, CITY, STATE, ZIP, PHONE, EMAIL, AGE)
2.RESERVATION RESID, RESDATETIME, CHECKINDATE, CHECKOUTDATE, ROOMTYPE, TOTALCOST, GUESTID)
3.CREDITCARD (CCNO, TYPE, EXPIRYDATE, GUESTID)
4.ITINERARY (ITINID, CHECKINDATETIME, CHECKOUTDATETIME, ADULTCOUNT, CHILDCOUNT, GUESTID, ROOMNO)
5.ROOM (ROOMNO, ROOMTYPE, DAILYRATE, AMENITIES)
6.BILL (BILLID, BILLDATE, AMOUNTDUE, ITINID, CCNO)
7.CHARGETYPE (CHARGEID, DESCRIPTION)
8.CHARGES (CHARGEID, ITINID, CHARGEDATETIME, AMOUNT, GUESTID)
Because this is a homework assignment, I don't want to just post the answer, but I have good clues for you.
Question 1: You'll need to make an internal select statement (subquery) to determine the average charge across all charges before you can compare against each charge. Your subquery might look something like this:
SELECT AVG(AMOUNT) "AvgCharge" FROM CHARGES
You could put this in the SELECT portion of your statement or as a Cartesian product.
Question 2: I'm guessing you'll need to join the ITINERARY, CHARGES, and CHARGETYPE tables together. Here's a link for JOINs in Oracle. Afterwords, you'll have to limit that statement to only show golf and dinner charges.
Let's break it down. The first thing you need is the name of teh guest. Well clearly that has to come fromteh guest table.
so you have
select FIRSTNAME, MIDINIT, LASTNAME,
From Guest
Now you only want guests with Itineraries so you do an inner join to Itinerary (hint you join on GuestID)
select FIRSTNAME, MIDINIT, LASTNAME, ItineraryID
From Guest
JOIN ITINERARY on GUEST.GUESTID = ITINERARY.GUESTID
Now you only want guests who have charges for that ITINERARY.
So you would think to join to CHARGES and CHARGETYPE (to get the type of charges) and use a where clause to limit the charges to the types you are interested in. But becasue you want to make sure you have both types of charges, you need to join to CHARGES and CHARGETYPE twice (I don't know about Oracle but in SQL server these would need to be aliased (I would call them C1 and CT1 and C2 and CT2) I would suspect the same for Oracle). The first join will have a where clause of CT1 = 'dinner' and the second grouping of the two tables would include a where clause of CT2 = 'golf'