MS Access Selecting Related Rows - sql

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]

Related

How to check if table relationship is one to many in SSMS

I'm writing some SQL code based on my tables but don't want to miss any edge cases. I'm wondering how do you check if there's a one to many relationship between two tables in SSMS
SELECT *
FROM Houses
JOIN Addresses
on Houses.Id = Addresses.HouseId
Unfortunately the data when queried doesn't give me any insight.
What I tried to do:
Checked table dependencies but that didn't give me any insight. It shows addresses are dependencies but no relationship details.
May I ask, is it possible to determine if one to one via SSMS?
You can run a query to determine how many values each house in the two tables. Well, in this case, we'll assume it is the primary key of houses and the values of HouseId are valid ids:
SELECT num_addresses, COUNT(*)
FROM (SELECT h.Id, COUNT(a.HouseId) as num_addresses
FROM Houses h LEFT JOIN
Addresses a
ON h.Id = a.HouseId
GROUP BY h.Id
) ha
GROUP BY num_addresses;
Then interpret the results:
If the only row returned has num_addresses of 1, then you have a 1-1 relationship.
If two rows are returns with values of 0 and 1, then you have a 1/0-1 relationship.
If multiple rows are returned and the minimum is 1 then you have a 1-n.
If multiple rows are returned and the minimum value is 0, then you have a 0-n.
You could extend this for more general relationships, but this answers the question you asked here.
The relationship between tables is shown by things called 'DATABASE - DIAGRAM'
Here is document about how to create database - diagram in SSMS.
How to create database diagram SSMS
Gordon Linoff response is perfect for the helicopter view -
To get all records side by side simply select all columns from both tables side by side with the left join
SELECT Houses.*, Address.*
FROM Houses
left JOIN Addresses on Addresses.HouseId = Houses.Id
union all
SELECT Houses.*, Address.*
FROM Addresses
left JOIN Houses on Houses.Id = Addresses.HouseId
Microsoft have implemented a reduced code method to do the same but I have not explored it so could not comment
https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/outer-joins?view=sql-server-ver15
What will be apparent is you will see Houses.ID and Addresses.HouseID side by side - An empty value in either means that the relevant table does not have a record for the relevant HouseID or ID
You can then cherry pick those edge case records as you see fit

Refer to different id's within the same query in SQL

I need to brind a lot of columns from several tables using LEFT JOIN. My starting point is the orders table and I bring the vendor name from the "Address_table". Then I add another table with order details and then the shipping information of each order detail.
My problem is that I need to bring a different record from "Address_table" to refer onether id's detailed in shipment table as of "origin_id" and "destination_id".
In other words, "address_id", "origin_id" and "destination_id" are all records from "Address_table". I brought the first one related to the vendor, how can I retrieve the other two?
Example
Thanks in advance
Your question is not exactly clear in terms of the tables and their relationships. It is, however, clear what the problem is. You need to join against the same table twice using different columns.
In order to do that you need to use table aliases. For example, you can do:
select *
from shipment s
left join address_table a on a.address_id = s.origin_id
left join address_table b on b.address_id = s.destination_id
In this example the table address_table is joined twice against the table shipment; the first time we use a as an alias, the second time b. This way you can differentiate how to pick the right columns and make the joins work as you need them to.

poor report performance when using with clause

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;

Inserting Into and Maintaining Many-to-Many Tables

SQLite3 user.
I have read thru numerous books on relational DBs and SQL and not one shows how to maintain the linking tables for many-to-many relationships. I just went through a book that went into the details of SELECT and JOINS with examples, but then glosses over the same when many-to-many relationships are covered. The author just showed some pseudo code for a table, no data, and then a pseudo code query--WTF? I am probably missing something, but it has become quite maddening.
Anyways, say I have a table like [People] with 3 columns: pID (primary), name and age. A table [Groups] with 3 columns: gID (primary), groupname and years. Since people can belong to multiple groups and groups can have multiple people, I set up a linking table called [peoplegroups] with two columns: pID, and gID both of which come from their respective tables.
So ,how do I efficiently get data into the linking table when INSERTING on the others and how do I get data out using the linking table?
Example: I want to INSERT "Jane" into [people] and make her a member of group gID 2, "bowlers" and update the linking table {peoplegroups] at the same time.
Later I want to go back and pull out a list of all of the bowlers or all the groups a person is part of.
If you already don't use primary and foreign keys (which you should!) I think you may need to consider using triggers in your design as well? So if you have a specific set of rules (e.g. if you want to create Jane with id = 1 and choose existing group 2, then after insert jane into people automatically create an entry pair personid=1,groupid=2 in the table peoplegroups. You can also create views with specific selects to see the data you want, for example if you want a query where you only show the peoples names and groups names you could create a view 'PeopleView':
SELECT P.PersonName, G.GroupName
FROM People P
INNER JOIN PeopleGroup PG ON P.PersonID = PG.PersonID
INNER JOIN Group G ON G.GroupId = PG.GroupID
then you can query 'PeopleView' saying
SELECT * FROM PeopleView WHERE GroupName = 'bowlers'
When inserting new data into the tables mentioned, the "linking" table that you are referring to needs to contain both primary keys from the other tables as foreign keys. So basically The [People] tables (pID) and the [Groups] table (gID) should both be foreign keys in the [PeopleGroups] table. In order to create a new "link" in [PeopleGroups] the record has to already exist in the [People] table as well as the [Groups] table BEFORE you try and create the link in the [PeopleGroups] table. I hope this helps

How can I compare two tables and delete on matching fields (not matching records)

Scenario: A sampling survey needs to be performed on membership of 20,000 individuals. Survey sample size is 3500 of the total 20000 members. All membership individuals are in table tblMember. Same survey was performed the previous year and members whom were surveyed are in tblSurvey08. Membership data can change over the year (e.g. new email address, etc.) but the MemberID data stays the same.
How do I remove the MemberID/records contained tblSurvey08 from tblMember to create a new table of potential members to be surveyed (lets call it tblPotentialSurvey09). Again the record for a individual member may not match from the different tables but the MemberID field will remain constant.
I am fairly new at this stuff but I seem to be having a problem Googling a solution - I could use the EXCEPT function but the records for the individuals members are not necessarily the same from one table to next - just the MemberID may be the same.
Thanks
SELECT
* (replace with column list)
FROM
member m
LEFT JOIN
tblSurvey08 s08
ON m.member_id = s08.member_id
WHERE
s08.member_id IS NULL
will give you only members not in the 08 survey. This join is more efficient than a NOT IN construct.
A new table is not such a great idea, since you are duplicating data. A view with the above query would be a better choice.
I apologize in advance if I didn't understand your question but I think this is what you're asking for. You can use the insert into statement.
insert into tblPotentialSurvey09
select your_criteria from tblMember where tblMember.MemberId not in (
select MemberId from tblSurvey08
)
First of all, I wouldn't create a new table just for selecting potential members. Instead, I would create a new true/false (1/0) field telling if they are eligible.
However, if you'd still want to copy data to the new table, here's how you can do it:
INSERT INTO tblSurvey00 (MemberID)
SELECT MemberID
FROM tblMember m
WHERE NOT EXISTS (SELECT 1 FROM tblSurvey09 s WHERE s.MemberID = m.MemberID)
If you just want to create a new field as I suggested, a similar query would do the job.
An outer join should do:
select m_09.MemberID
from tblMembers m_09 left outer join
tblSurvey08 m_08 on m_09.MemberID = m_08.MemberID
where
m_08.MemberID is null