Best way to join multiple foreign keys to same table - mysql

I have a table "user" with a few rows that are both foreign keys for the same table "content" kinda like this:
user.id
user.bio
user.signature
content.id
content.text
I know this is not the right way to do this from a normalization standpoint, but the "content" table is from a separate DB that I cant modify. And I dont want to duplicate the data.
Im having a problem finding a good way to join them. All I have been able to do is this, but this seems wasteful.
SELECT bio.bio, text.text
FROM(
SELECT content.text as bio
FROM content, user
WHERE user.bio = content.id
AND user.id = 4) AS bio,
SELECT content.text as content
FROM content, user
WHERE user.signature = content.id
AND user.id = 4) AS content

You can join one table multiple times if you give each instance a different alias:
SELECT bio.text, sig.text
FROM user u
JOIN content bio ON u.bio = bio.id
JOIN content sig ON u.signature = sig.id
WHERE u.id = 4

Related

LEFT JOIN in MySQL query

I have two database tables, one is named "articles", and the other one is "users"
the structure of articles is as follows:
article_id article_title user_id
The structure of users is:
user_id user_fullname password
I wish to retrieve a list of all articles from the table "articles", but would like to attach each article's user_fullname. I think this may require "LEFT JOIN", so I made the following attempt in MySQL prompt.
> SELECT * FROM articles A LEFT JOIN users U on U.user_id = A.user_id;
but somehow I don't see the user_fullname printed out with this command. I need some help with the correct syntax. Thank you!
A full join seems more appropriate, each article must have an author, so there should be a corresponding entry in the users table:
SELECT *
FROM articles a
JOIN users u USING(user_id);
Note: USING here is the same as ON a.user_id = b.user_id and can only be used if the column name is the same in both tables.

Get Data From 2 Tables in One Query

I am trying to retrieve data for my notification system. I have three tables. One table (notifications) holds the actual information for the notification itself. I have two other tables to keep track of who gets certain notifications. There are two types of notifications, user and global. A global notification goes to all users while a user notification only goes to specific users. For this I have two tables, notifications_users and notifications_global. The table structures are below:
notifications (id, title, url, start, end)
notifications_users (notification_id, user_id, viewed)
notifications_global (notification_id, user_id, viewed)
What I want to do is to grab the notification title and url (from notifications table) along with the viewed value for all notifications that go to a specific user from both notifications_users and notifications_global tables. Would a UNION query be the best option here? I thought about just separating the queries but then I have two different arrays to loop through in my PHP script which I do not want. There has to be a way to grab all of this data with one query into one array. The following gives me an empty set:
SELECT notification.title, notification.url
FROM notifications
RIGHT JOIN notifications_users ON notifications.id = notifications_users.notification_id
RIGHT JOIN notifications_global ON notifications.id = notifications_global.notification_id
WHERE notifications_users.user_id = 11508 AND notifications_global.user_id = 11508;
SELECT a.title, a.url, b.viewed as 'User View', c.viewed as 'Global View'
FROM Notifications a
INNER JOIN Notifications_Users b
ON a.id = b.notification_id
INNER JOIN Notifications_Global c
ON b.notification_id = c.notification_id
WHERE b.user_id = 11508 and c.user_id = 11508
I think I might have been over-complicating this a bit. I just wrote the two queries for each table separate and then put UNION between them. If anyone is interested, here is what I ended up going with.
(SELECT notification_id, notification_title, notification_url, tbl_notifications_users_lookup.viewed
FROM tbl_notifications
INNER JOIN tbl_notifications_users_lookup ON tbl_notifications.id = tbl_notifications_users_lookup.notification_id
WHERE tbl_notifications_users_lookup.user_id = 11508)
UNION
(SELECT notification_id, notification_title, notification_url, tbl_notifications_global_lookup.viewed
FROM tbl_notifications
INNER JOIN tbl_notifications_global_lookup ON tbl_notifications.id = tbl_notifications_global_lookup.notification_id
WHERE tbl_notifications_global_lookup.user_id = 11508);

PHP/MySQL Many to Many. How?

I recently thought that storing an array in MySQL database would solve my problems... then I went and banged my head on a wall until I realised that there was an easier solution to my problem. Unfortunately I can't seem to figure out what the hell I need to do.
I have two tables. User and Entry. Each user can be the Author of any number of entries. One to many right? Well the problem comes from the fact that each entry can have many users. -_-;
As you can imagine, doing this using arrays would be...not only cumbersome but also stupid, especially if someone managed to accumulate 2000 entries. I had anticipated that I might need to create an extra table and some resources do seem to suggest it but the resources aren't as clear as I would have hoped. I will need to get all the users for a post and somewhere else, I'll need to get all the posts for a user.
Can someone explain the best way of doing this? (Without using arrays of course =p)
you need to make 3 tables:
user (primary key = id)
id
name
...
entry (primary key = id)
id
text
...
userentry (primary key = complex key user,entry)
user
entry
if you want to get an entrys users, just do
SELECT
user.*
FROM
userentry
INNER JOIN
user
ON
userentry.user = user.id
WHERE
userentry.entry = [your entry-id]
and to get all entrys of a user, just do it the other way around:
SELECT
entry.*
FROM
userentry
INNER JOIN
entry
ON
userentry.entry = entry.id
WHERE
userentry.user = [your user-id]
The best way to do this is to have three tables:
Users:
Id,
Name,
...
Posts:
Id,
PostName,
...
UserPosts:
Id surrogate key,
UserId,
PostId.
Then to get all the users for a post
SELECT u.*
FROM users u
INNER JOIN posts p ON u.id = p.userid
WHERE p.id = apostid
To get all the posts for a user:
SELECT p.*
FROM posts p
INNER JOIN users u ON u.id = p.userid
WHERE u.id = auserid

Connecting table with multiple foreign keys in mysql

I have a database table with the following information :
owner.primaryitowner,
owner.secondaryitowner,
owner.primarybusinessowner,
owner.secondarybusinessowner
The issue, is the owners are only stored as emails. There is another table I normally inner join users on users.username = owner.primaryitowner to get users.displayname so the data reads correctly. The issue is I need to do this for all 4 columns, and when I can only figure out how to connect 1 column in a query. Thanks for the help
P.S. I cannot change the database I am only a report writer.
Assuming you want all the display name for all owners, try something like this:
select u.displayname
from users u
inner join owners o on
o.primaryitowner = u.username
or o.secondaryitowner = u.username
or o.primarybusinessowner = u.username
or o.secondarybusinessowner = u.username

Mysql fetching data from multiple tables

I am having three tables
user(id,fname,lname)
picture(picid,pic_path,userid)
friends(friend_of,friends_id,status)
I want to fetch id,fname,lname,pic_path for all friends_id of friends_of=1
picture path may be null
Thankx in advance.
What you're looking for is called a join. In particular, you're looking for a JOIN and a LEFT JOIN.
SELECT
user.id, user.fname, user.lname, picture.pic_path
FROM
friends
JOIN user
ON user.id = friends_id
LEFT JOIN picture
ON userid = user.id
WHERE
friends.friend_of = 1
This will only work though if there's a maximum of 1 entry in picture.
Though this answers your immediate question, I suggest you become very familiar with joins. They're one of the fundamental operations of a relational database. (Note that a join essentially is a mathematical relation)
Try this
SELECT u.*,p.*,f.*
FROM USER u
LEFT JOIN picture p ON p.user_id = id
INNER JOIN friends f ON f.friends_of = u.id
WHERE f.friends_id = 1
For querys like that you need to understand and employ the relations between your entities. Then you work in two steps: selection and projection and contrary to what SQL-syntax may imply the part before the FROM keyword is the projection.
First we compile data. Clearly we need the data from all three tables and we need it once. So at first we construct all possible combinations, by joining all three tables. In SQL this is done in the FROM part, i.e.
FROM friends f, picture p, user u
f, p and u are aliases which serve the purpose of saving us the efford of typing the full table names in the following.
Now we have all possible combinations. Let's select the ones we want:
I suppose every picture in your DB belongs to a user which is stored in your DB as well. So my assumption is that you only want pictures associated to a user. Hence we have a first restrictions on all the combinations we made before! The restriction derived from the (probable) meaning of the data stored in you database and stated as:
u.id = p.userid
(Notice: by applying this restriction to combination above we "select" only certain combinations.)
Then you already stated another restrictions as a request "friends_of=1" to associate this constraint on the combination we write:
f.friends_of=1
Then we combine your request "friends_of=1" with the other data by:
f.friend_of = u.id
This constraint selects only those users who are a friend of somebody. Now we can combine these constraints. As we want all constraints to be satisfied we AND them in a WHERE statement:
WHERE u.id = p.userid AND f.friend_of = u.id AND f.friends_of=1
The ordering does not affect meaning (in this case. But let's rethink those constraints:
u.id = p.userid : we want information about the user and the pictures associated with that user
f.friend_of = u.id : we are looking for a users who are friends of somebody
f.friends_of=1 : we are looking for friends of a particular somebody
Now we project the data stored in our DB to what we want. We want all the user data and picture paths. In SQL:
SELECT u.*,p.pic_path
Now we put everything together.
SELECT u.*,p.pic_path FROM friends f, picture p, user u WHERE u.id = p.userid AND f.friend_of = u.id AND f.friends_of=1
To allow for friends that don't have a picture associated with them (note: that's very different to pic_path being NULL) you need an outer join, which means you also want combinations with empty sets. That's where my MySQL is not so good but I'd guess you'd generate all combinations you want (and many more) with:
FROM friends f JOIN user u LEFT JOIN picture p ON u.id = p.userid
and
SELECT u.*,p.pic_path FROM friends f JOIN user u LEFT JOIN picture p WHERE f.friend_of = u.id AND f.friends_of=1
Notice, that the constraint that may be violated has been made explicit by moving it from the general selection to the generation of the data combinations as a rule on how to create combinations. And yes, it's a shortcut instead of following through the idea of selection and projection.