What is the best way to join humongous table two or more times?
For example In this fictitious example, we have students table, student record who has TUTOR_ID column is a reference to the same table to another student.
What I am trying to accomplish is a report that will find all tutors that share the same students.
So I have built a query like this:
First time to find parent child relationships
Second time to find all tutors that share the same students
I tried to use "with clause" but query performance is really bad
Is there a better approach to take?
WITH STUDENT_TMP_TABLE AS (
select
TUTORS.STUDENT_IDENTIFIER as TUTOR_STUDENT_IDENTIFIER,
CADETS.STUDENT_IDENTIFIER as CADET_STUDENT_IDENTIFIER
FROM V_STUDENTS_RELATIONS TUTORS
INNER JOIN V_STUDENT_RELATIONS CADETS ON CADETS.TUTOR_ID = TUTORS.STUDENT_IDENTIFIER AND TUTORS.TUTOR_ID IS NULL
WHERE -- ? conditions truncated
)
SELECT
*
FROM STUDENT_TMP_TABLE STUD_TMP1
JOIN STUDENT_TMP_TABLE STUD_TMP2
ON STUD_TMP1.TUTOR_STUDENT_IDENTIFIER <> STUD_TMP2.TUTOR_STUDENT_IDENTIFIER
AND STUD_TMP1.CADET_STUDENT_IDENTIFIER = STUD_TMP2.CADET_STUDENT_IDENTIFIER;
Related
Ok, so I have been looking everywhere and i cant seem to find anything.
Heres what Im trying to do:
SELECT SFirstName, SLastName
FROM Advisors
WHERE Students <= ('1') and Students.AdvisorID=Advisors.AdvisorID;
The SName is student names, and i need to basically list advisors based on the number of active students for each, and then filter out any with more than one student.
Heres an attempt to code this with the DBO names and all.
SELECT AFirstName, ALastName
FROM DBO.Students, DBO.Advisors
WHERE Advisor.AdvisorID=Student.AdvisorID AND >1;
Basically the advisorID is a Foreign Key within the Students table, and I need to match it with the advisor table and then the >1 statement. I dont know how to reduce results by number yet however.
Whenever I try this it tells me it cannot find the advisor.advisorID or the student.AdvisorID. how would i do this while still using the foreign key from one and the primary key from the other to cross check matches.
If I understand you question correctly, you want to list the Advisors with less than 1 Students. If so, what you need is a LEFT JOIN coupled with COUNT and HAVING:
SELECT
a.AFirstName, a.ALastName
FROM dbo.Student s
LEFT JOIN dbo.Advisors a
ON a.AdvisorID = s.AdvisorID
GROUP BY
a.AdvisorID, a.AFirstName, a.ALastName
HAVING
COUNT(s.AdvisorID) <= 1
Notes:
Avoid using the old-style JOIN syntax.
Alias your tables to improve readability.
After looking at example after example of both inner joins and subqueries as fields, I'm apparently not getting some aspect, and I would appreciate help please. I am trying to write one query that must, alas, run in MS Access 2007 to talk to an Oracle database. I have to get values from several different places for various bits of data. One of those bits of data is GROUP_CODE (e.g., faculty, staff, student, alum, etc.). Getting that is non-trivial. I am trying to use two inner joins to get the specific value. The value of borrower category must be the value for my main row in the outer query. Here is what this looks like:
Patron table Patron_Barcode table Patron_Group table
Patron_id Barcode Patron_Group_iD
Barcode Patron_Group_id PATRON_Group_Code
I want to get the PATRON_GROUP.PATRON_GROUP_CODE. This is only one of 35 fields I need to get in my query. (Yes, that's terrible, but wearing my librarian hat, i can't write the Java program I'd like to write to do this in a snap.)
So as a test, I wrote this query:
select PATRON.PATRON_ID As thePatron,
(SELECT PATRON_GROUP.PATRON_GROUP_CODE As borrowwerCategory
FROM (PATRON_GROUP
INNER JOIN PATRON_BARCODE ON PATRON_GROUP.PATRON_GROUP_ID = PATRON_BARCODE.PATRON_GROUP_ID
) INNER JOIN PATRON ON PATRON_BARCODE.PATRON_ID = thePatron.PATRON_ID
));
I don't know what I'm doing wrong, but this doesn't work. I've written a fair amount of SQL in my time, but never anything quite like this. What am I doing wrong?
PATRON.BARCODE is the foreign key for the BARCODE table.
PATRON_BARCODE.PATRON_GROUP_ID is the foreign key for the PATRON_GROUP table. PATRON_GROUP_CODE in PATRON_GROUP is he column value that I need.
PATRON.BARCODE -> BARCODE.PATRON_GROUP_ID -> PATRON_GROUP.PATRON_GROUP_CODR>
The main table, PATRON, will have lots of other things, like inner and outer join to PATRON_ADDRESS, etc., and I can't just do an inner join directly to what I want in my main query. This has to happen in a subquery as a field. Thanks.
Ken
I need to write a query that generates a list of participantID's that fit certain experiment and participation criteria. I have these tables:
Participation that has participantID, participationDate, and experimentID.
Experiment that has experimentID, keyword.
ParticipantRegistry that has participantID, and a bunch of irrelevant fields.
My conditions are:
Keyword<>"Robots"
AND ParticipationDate<#12/1/2014#
AND Experiment.ExperimentID=Participation.ExperimentID
Here's the code I wrote which works for finding participants in the Participation table i.e. have participated in an experiment:
SELECT ParticipantID, Keyword
FROM Experiment, ExperimentParticipation
WHERE Experiment.ExperimentID = ExperimentParticipation.ExperimentID
AND Keyword<>"Robots"
AND ParticipationDate <#12/1/2014#
So, the ParticipantRegistry table has a whole list of participantID's (even those not included in the participation table i.e. have never participated in experiments).
I want to create a query that has the participants who fit my criteria which I was able to achieve with those who participated in experiments AND those in the ParticipantRegistry table who have not participated in any experiments. The problem is participants who have not participated are not in the Participation table, so I cannot use the null function.
Maybe you are looking for left join.
You could completely select your participants from the ParticipantRegistry (left join would hold them still, even though some of them are not having experiments to be joined with), and join it with the Participation. Then at last join it with the Experiment.
UPDATED :
SELECT ParticipantRegistry.ParticipantID, Keyword
FROM (ParticipantRegistry
LEFT JOIN Participation ON (ParticipantRegistry.ParticipantID = Participation.ParticipantID AND ParticipationDate <#12/1/2014#))
LEFT JOIN Experiment ON (Participation.ExperimentID = Experiment.ExperimentID AND Keyword<>"Robots")
I have two tables in a Database
and
I need to retrieve the number of staff per manager in the following format
I've been trying to adapt an answer to another question
SELECT bankNo AS "Bank Number",
COUNT (*) AS "Total Branches"
FROM BankBranch
GROUP BY bankNo
As
SELECT COUNT (*) AS StaffCount ,
Employee.Name AS Name
FROM Employee, Stafflink
GROUP BY Name
As I look at the Group BY I'm thinking I should be grouping by The ManID in the Stafflink Table.
My output with this query looks like this
So it is counting correctly but as you can see it's far off the output I need to get.
Any advice would be appreciated.
You need to join the Employee and Stafflink tables. It appears that your FROM clause should look like this:
FROM Employee INNER JOIN StaffLink ON Employee.ID = StaffLink.ManID
You have to join the Eployee table twice to get the summary of employees under manager
select count(*) as StaffCount,Manager.Name
from Employee join Stafflink on employee.Id = StaffLink.EmpId
join Employee as Manager on StaffLink.ManId = Manager.Id
Group by Manager.Name
The answers that advise you on how to join are correct, assuming that you want to learn how to use SQL in MS Access. But there is a way to accomplish the same thing using the ACCESS GUI for designing queries, and this involves a shorter learning curve than learning SQL.
The key to using the GUI when more than one table is involved is to realize that you have to define the relationships between tables in the relationship manager. Once you do that, designing the query you are after is a piece of cake, just point and click.
The tricky thing in your case is that there are two relationships between the two tables. One relationship links EmpId to ID and the other links ManId to ID.
If, however, you want to learn SQL, then this shortcut will be a digression.
If you don't specify a join between the tables, a so called Cartesian product will be built, i.e., each record from one table will be paired with every record from the other table. If you have 7 records in one table and 10 in the other you will get 70 pairs (i.e. rows) before grouping. This explains why you are getting a count of 7 per manager name.
Besides joining the tables, I would suggest you to group on the manager id instead of the manager name. The manager id is known to be unique per manager, but not the name. This then requires you to either group on the name in addition, because the name is in the select list or to apply an aggregate function on the name. Each additional grouping slows down the query; therefore I prefer the aggregate function.
SELECT
COUNT(*) AS StaffCount,
FIRST(Manager.Name) AS ManagerName
FROM
Stafflink
INNER JOIN Employee AS Manager
ON StaffLink.ManId = Manager.Id
GROUP BY
StaffLink.ManId
I don't know if it makes a performance difference, but I prefer to group on StaffLink.ManId than on Employee.Id, since StaffLink is the main table here and Employee is just used as lookup table in this query.
I have 2 tables with a many-to-any relationship. For the example we will call the tables "Guys" and Girls" There is a junction table that contains the related primary keys...who has dated who.
If I want to find all the girls that Guy 1 has dated, I do a select on the junction table selecting all girls with guys.ID. This give me a RecordSet. Now to find the names of the girls, I need to select from the girls table a row using the key from each RecordSet row.
Isn't there an easier way? Since I've defined the relationships in Access I would think that there must be a way to build a single query. How do I do that?
SELECT girls.name
FROM (guys
INNER JOIN junct ON guys.guyID = junct.guyID)
INNER JOIN girls ON junct.girlID = girls.girlID
WHERE guys.guyID = [whatever id you're looking for]