MySQL Views: Sub-Joins - sql

I am wanting to have a view table that aggregates rows from four tables.
The first primary table is client and is just a primary key unique id and a profile_id. The second table, profile, holds all of the firstname, address, zipcode kind of information. The third table is email; there can be many email objects to one client object but there is only one email object with the primary column flagged true; the fourth table is phone - this is also a many to one relationship (there can be cellphones, homephones, fax numbers, etc...) and only one object can have the primary column flagged.
JOINing the client table with the profile table is easy as it's one to one; what I want advice on is how to go about selecting an email and phone object based on the primary column (rather than the first JOINed result).
Any resources I can be pointed to would be greatly appreciated; as I have been searching for material for a few days.
Thank you in advance!

There shouldn't really be any problems to joining email and phone too. Just join them in another straight forward join and add WHERE phone.primary = TRUE as an ordinary WHERE-claus.
The following, I think, should do it:
SELECT *
FROM client
JOIN profile
ON profile.client_id = client.id
JOIN email
ON email.client_id = client.id
JOIN phone
ON phone.client_id = client.id
WHERE phone.primary = TRUE AND
email.primary = TRUE

select whatevercolumnsyouwant
from client
join profile using (profile_id)
join email on client.profile_id = email.profile_id
and email.primary = 1
join phone on client.profile_id = phone.profile_id
and phone.primary = 1
where client.id = :whateverclientid
the key point is that ON subclauses of JOIN clauses can specify several conditions (in AND, OR, whatever) just like WHERE clauses can but with a more "specific" purpose!

Related

How to compare attributes from tables that are 3 relationships apart in SQL

I need to produce some sample SQL for a database to be created with an ERD that I have already made.
The required query is https://imgur.com/vDvL1ZS
and the ERD being used is https://imgur.com/a/hzTQhPU
I've assumed that I need to select from the 3 tables (Message, Chat, UserChat) but I don't understand how the query would be able to match up each instance of messages and users. I've tried to make somewhat of a starting point below but can't see what else would be required.
SELECT MessageID, ChatID, IsText, MessageText, FileName, MessageFile
FROM tbl_Message, tbl_Chat, tbl_UserChat
WHERE tbl_Message.DateSent > UserChat.LastOpened
AND tbl_User.UserID = ‘1044’
AND tbl_Chat.ChatID = ‘139’
A primary key is a field or set of fields which are unique across your table. Each row has its unique primary key.
A foreign key is a field or set of fields, containing only values that are another's table primary key. It is basically a reference to another table.
You can link tables that have references to each others using joins. Here, you are trying to link the Message, Chat and UserChat tables, like so:
select
*
from
UserChat
join
Chat on UserChat.ChatID = Chat.ChatID
join
Message on Chat.ChatID = Message.ChatID
As you can see, I "chained" the joins as the relationships are in the diagram.
Now we got our tables linked, we can add our filters, and only select the Message fields:
select
Message.*
from
UserChat
join
Chat on UserChat.ChatID = Chat.ChatID
join
Message on Chat.ChatID = Message.ChatID
where
UserChat.ChatID = y -- Filter the correct chat
and
UserChat.MessageID = x -- Filter the correct user
and
UserChat.LastOpened < Message.DateSent -- Filter only unread messages

Retrieve columns multiple times using SQL

In Access 2007 I have a table named Registars with a list of people and a table named Related.
Registars has a Primary key of Reg_ID and a field of Reg_Surname and a field of Reg_Forename.
Related table has a field of Reg_Person_ID and a field of Rel_Person_ID where both are primary keys (or combination key) a third field is relation_Type, i.e. cousin, sister etc.
What I am trying to write is a SQL script that will interrogate these two tables and using each record in the Related table output the ID of the first person and then their Forename then their surname then the second persons ID then thgeir forename then their surname. That is;
Reg_Person_ID Reg_Forename Reg_Surname Rel_Person_ID Reg_Forename Reg_Surname
So far what I have tried using SQL hasn't worked. Below is a screen dump of the two tables with data and the desired output.
SELECT
reg.Reg_Person
,reg.Reg_Forename
,reg.Reg_Surname
,rel.Rel_Person_ID
,rr.Reg_Forename AS Rel_Forename
,rr.Reg_Surname AS Rel_Surname
,rel.Relation_Type
FROM
Registrars reg
LEFT OUTER JOIN
Related rel
ON reg.Reg_ID = rel.Reg_Person_ID
LEFT OUTER JOIN
Registrars rr
ON rel.Rel_Person_ID = rr.Reg_ID

Update Table Column From Another Table?

So I have two tables. Say one table has a list of students, a student ID for each student, and a home address for each student.
Then you have another table that has a subset of the students in the first able, (and they are in a completely different order) with updated addresses and a student ID.
I need a query that can match the student ID of the two tables, and thereby update the address from the first table, using what is in the second table.
This is the query I tried, but no luck:
UPDATE Roster, UpdatedRoster
SET Roster.Address = (SELECT Address FROM UpdatedRoster WHERE Roster.StudentID = UpdatedRoster.StudentiD)
WHERE Roster.StudentID = UpdatedRoster.StudentiD
Any help here would be greatly appreciated.
Update: This is on Microsoft Access FWIW.
UPDATE Roster
SET Roster.Address = UpdatedRoster.Address
FROM Roster, UpdatedRoster
WHERE Roster.StudentID = UpdatedRoster.StudentiD

One to many relationships in T-SQL

I need to figure out how to find a certain group of records using T-SQL and I'm having trouble figuring out how I would need to create the WHERE clause to do this.
I have a SQL 2008 R2 system that I'm working with, and in this database there are a couple of tables. One contains personnel records, and another contains addresses. The addresses relate to the personnel records by a foreign key relationship. So for example, to get a list of all personnel and all of their associated addresses (a single person could have multiple addresses) I could write something like this:
SELECT id, name FROM personnel p
INNER JOIN address a
ON p.id = a.personnelid
However, each address has a column called isprimary, that is either 0 or 1. What I need to do is figure out how to find all personnel who do not have an associated address with isprimary set to 1. Or records that have no primary address.
Currently my thought is to build a temporary table with personnel who have addresses that aren't marked as primary. Then cycle through those and build a subset that have a primary address.
Then subtract the Personnel With Primary table from the results of Personnel With Non-Primary and I should have my list. However, I'm thinking that there has to be a more elegant way of doing this. Any ideas?
Try this, it should get all Personnel rows with no matching primary address:
SELECT *
FROM Personnel p
WHERE NOT EXISTS
(SELECT * FROM Address a WHERE a.personnelId = p.id AND a.isprimary = 1)
SELECT id, name FROM personnel p
INNER JOIN address a
ON p.id = a.personnelid
AND a.isprimary = 0
This ends up beeing a Left anti semi join pattern
and can be written like this:
SELECT id, name FROM personnel p
LEFT OUTER JOIN address a
ON p.id = a.personnelid
AND a.isprimary = 1
WHERE a.personnelId IS NULL
It can be interesting to test different ways because query plan are often not the same.

Multiple foreign keys from one table linking to single primary key in second table

I have a database with three tables, a household table, an adults table and a users table. The Household table contains two foreign keys, iAdult1ID and iAdult2ID. The Users table has a iUserID primary key and the Adult table has a corresponding iUserID foreign key. One of the columns in the Users table is strUsername, an e-mail address.
I am trying to write a query that will allow me to search for an e-mail address for either adult that has a relation to the household. So I have two questions, assuming that all the values are not null, how can I do this?
And two, in reality, iAdult2ID can be null, is it still possible to write a query to do this?
Thanks for your help. Let me know if you need any more information.
Yes, you just left join to the same table twice:
select u1.strUsername, u2.strUsername
FROM Household h
LEFT JOIN Adult a1 on a1.ID = h.iAdult1ID
LEFT JOIN Users u1 on u1.ID = a1.iUserID
LEFT JOIN Adult a2 on a2.ID = h.iAdult2ID
LEFT JOIN Users u2 ON u2.ID = a2.iUserID
While the accepted answer is correct I thought it would be helpful to point out that the original problem is a consequence of how the data is modeled.
Ideally you should move the AdultIds out of the HouseHold table and into a new table called HouseholdAdults which contains both the HouseholdId and the iAdultId. Then you can have one or more adults per household.
Heres a screenshot to illustrate what I mean.
Currently you have restricted the relationship between adults and household to at least one and no more than two. What about houses with no adults or three? Also, you can't add a household record before adding an adult record? Where do you store information about an adults relationship to a household? For example, who is the owner, tenant, when they moved in, bought it etc. Basically anything relevant to the relationship.
These are all probably non-issues for you at the moment but still worth some thought I think.
This remodeling then resolves the issues you have with querying the data. With the new table in place to join the household table and the adult table you can easily query the relationship with the following.
SELECT Adult.iAdultId, Household.HouseHoldId, Users.strUserName FROM Adult
INNER JOIN HouseholdAdults ON Adult.iAdultId = HouseholdAdults.iAdultId
INNER JOIN Household ON HouseholdAdults.HouseholdId = Household.HouseHoldId
INNER JOIN Users ON Adult.iUserId = Users.iUserId
Heres some links explaining it further.
Many-to-Many relations
Database normalization