MySQL Design Clarification - php

I'm new to MySQL but have a pretty solid background in a wide variety of programming languages.
Right now I'm designing my first database from the ground up. I understand the basic functionality of MySQL tables and what a relational database is but I'm having trouble wrapping my head around a few things so I'm posting this for help (searching hasn't worked, the terms I've been using are too general and I don't know how to narrow it down). Here's where I'm stuck:
I want to pull Facebook data, specifically interests ("likes") and user location.
If this were some OO language I would just create a data structure for Users with all of the info in it (Facebook ID, interests as an array, location) but I'm not sure how to recreate this in MySQL.
Right now I'm thinking of creating a users table with
Facebook ID (primary key?)
Name
Location
Join date
Then creating an interests table with
Interest name (index, sorted alphabetically?)
Maybe a count of users with this interest
Foreign key that relates back to each user
I think this is where my lack of understanding comes in. How do I replicate the concept of a list or array in MySQL in a way that allows me to map each interest to each user who has "liked" that interest?
Any other suggestions, thoughts, or directions to good tutorial sites are greatly appreciated. I'm a tactile learner so getting my hands dirty with a tutorial would be great for me, I just haven't found one that covers this yet.

You could use a third table that would link the interests table to the user table. There would only be a record if the user liked that interest:
Table User_Interest:
Interest_ID
User_ID
To get a list of a user with all of their interests:
SELECT u.Name, i.Interest_Name
FROM Users AS u
INNER JOIN User_Interest AS ui ON ui.User_ID = u.ID
INNER JOIN interests AS i ON i.ID = ui.Interest_ID
WHERE u.Name = 'Tom Jones'
To get a list of a particular interest and all users that liked:
SELECT u.Name, i.Interest_Name
FROM Users AS u
INNER JOIN User_Interest AS ui ON ui.User_ID = u.ID
INNER JOIN interests AS i ON i.ID = ui.Interest_ID
WHERE i.Interest_Name = 'Hiking'

This type of setup is called a "many to many" relation. To do this, you will need 3 tables. 2 tables which contain your data and the last table a mapping table.
Here is an example of a many to many relation ship where the two objects are Students and Courses
Example
Your user table looks like this:
(ID_User, User_Name, ...)
Your interest table looks like this:
(ID_Interest, Interest_Name, ...)
Now your mapping table will look like this:
(ID_User, ID_Interest)
Sample Data
Now lets put some data in the tables
User_Table
------------------------
ID_user | Username | ...
------------------------
1 John
2 Mark
3 Foo
4 Bar
Interest_Table
----------------------------------
ID_Interest | Interest_Name | ...
----------------------------------
001 Pop
002 Rock
003 Alternative
004 Rap
User_To_Interest (Mapping Table)
---------------------------
ID_user | ID_Interest
---------------------------
1 001
1 003
3 002
2 004
4 001
Examining this
Ok so here if you analyze what has been set up, we are mapping users to interests. The mapping table sort of adds wires from the User object to an interest object.

Related

How do I iterate all rows from two tables connected by foreign key into a single table in PHP, CodeIgniter, MySQL

Say I have Table A and Table B in my SQL database.
TABLE A (Users)
userID
Name
Contact
userA
John
2292
userB
Dave
3383
TABLE B (Sports)
sportID
Name
trainer_userID
sportA
Basketball
userB
sportB
Baseball
userA
sportC
Soccer
userC
On my PHP page, I want to combine the two tables, such that the foreign key trainer_userID connects to their respective users. I can already iterate through each users and show Table A, but can't think of ways to combine both tables such that the output would be:
userID
Name
Contact
Sport Handled ID
Sport Handled
userA
John
2292
sportB
Baseball
userB
Dave
3383
sportA
BasketBall
Look up JOINS in SQL. This is exactly what relational databases are
for. Don't implement sql in loop, databases do it better. Welcome to
SO. – danblack 35 mins ago
Solved my problem using the JOINS technique and by using databases instead of looping.
SELECT * FROM tableA
INNER JOIN tableB
ON tableA.userID = tableB.trainer_userID;

multiple tables select

I don't know if it's possible but this is what I want to do.
I have three tables
Accounts
id | username | pass
Cars
id | plate | id_ac | kilometers // in the id_ac I add manual the id of the car's owner.
Trips
id | plate | places | date | active
Now I want when the user is logged in to see tha Trips that are active with his car.
So I want to
SELECT from Trips the plate, places, date WHERE active=0 AND id= ? (the logged user's id)
But the table trips doesn't have the id of the owner of the car. So I want somehow to select the values of the table Trips of the car that logged user owns.
Any idea how can I do that?
You should have a look at table joins. This looks like it is what you are looking for:
SELECT t.plate, t.places, t.date FROM Trips as t JOIN Cars as c ON t.plate = c.plate WHERE t.active = 0 AND c.id_ac = ?
Have a look at this. This is a pretty nice way of explaining the table joins.
http://www.sql-join.com/sql-join-types
I am not getting into DB architecture and deeper stuff, but it can help you with your task at hand
What you are referring to is primary and forgein key.
Your primary key is a unique key, which can identify every record in your table. In your user table that is the id. It has to be unique.
When you are now creating trips in your trips table, you will have to "link" your record to the specific user. Here you are referring to the primary key in user's table. So you have a new column user_id inside your trips table, where you will store the user id, who is connected to that trip.
When using the user id in other tables, you are having a "foreign key".
For each trip you will have to create a foreign key for the car and for the user. This can be the number plate and the user id.
If you want to see all the tracks for a specific user, you can make a JOIN with the user id in tracks. If you want to see all tracks for one car, you will just JOIN with the plate.
(I can just suggest reading some information about primary/ foreign key. It is fundamental when designing a database structure as you did above.)

Getting data from 2 tables with relationship with WHERE clausule

I've been following the PHP Authentication Tutorial en managed to get it working.
Now I want to add a function to my navbar. I will try to explain and hopefully someone has the answer.
I have the 2 user tables, users and user_permissions.
In the user table there are additional columns named district_id, district, gemeente_id and gemeente. I also have 2 extra tables in the database called districten and gemeenten.
The districten table has 2 colums. id and district which holds the unique ID and the name. The gemeente table has at least these 3 columns id, district_id and gemeente.
Here is what I would like to happen:
When the user logs in the query will give a result in an <ul> in the navbar where it will show all values (column gemeente) from the gemeenten table where the user has been assigned to.
Example:
User ZZZ is assigned to district A.
This district holds 4 gemeenten : City 1, City 2, City 3 and City 4
When the user logs in, he should
only see the cities from the District A.
I don't know how to get this working in Slim2 Framework and integrated in the PHP Authentication code. So any help is much appreciated.
First you have to normalize your table and get rid of redundant information since it's hard to maintain it in relational database(I assume here you're using relational database like MySQL).
So basically each user is assigned to gemeente, each gemeente assigned to district and district in his turn has cities(gemeenten). In user table you only need the gemeente_id. The schema of districten and gemeente seems fine.
There are two way how to retrieve needed data: by running 2 queries(1 for fetch user's district; 2nd for fetch district's cities) and run everything in one query. Which way to choose is up to you.
1st approach:
SELECT d.id FROM district AS d LEFT JOIN gemeente AS g ON g.district_id=d.id LEFT JOIN user AS u ON u.gemeente_id=g.id WHERE u.id=<user_id>
SELECT g.id, g.gemeenten from gemeente as g where g.district_id = <res_of_prev_query>
2nd approach:
SELECT
g.id, g.gemeenten
FROM gemeente AS g
LEFT JOIN
districten AS d
ON g.district_id=d.id
INNER JOIN (
SELECT DISTINCT district_id, u.id AS user_id
FROM gemeente as gg
INNER JOIN user AS u
ON u.gemeente_id=gg.id) AS ud
ON ud.district_id=g.district_id
WHERE ud.user_id=<user_id>
You need transform this query to your ORM/ActiveRecord, run it and display the ul list
UPD: I've updated my answer. Thanks #DarkBee for pointing me to my mistake

PHP and MySQL many-to-many question

Still wrapping my head around SQL and PHP, but hope someone can help with this:
I have the following tables:
1.
user table
- id
- name
- email
2.
user_group table
- user_id
- group_id
3.
group table
- id
- group_name
There is a many-to-many relationship between the user table and the group table. Now what I am trying to do build a browse users page which lists all the users in the system along with the groups that they belong to, so the page would look something like this:
Name: John Doe
Groups: football, tennis, swimming
Name: Jane Doe
Groups: hockey, basketball
Name: Jim Doe
Groups: hockey, football, rugby
etc. etc.
To accomplish this, I have the following SQL:
SELECT `user`.name, `group`.name
FROM `user`, `user_group`, `group`
WHERE `user`.id = `user_group`.user_id
AND `group`.id = `user_group`.group_id
GROUP BY `user`.id, `group`.id
which returns results as follows:
1. John Doe | football
2. John Doe | tennis
3. John Doe | swimming
4. Jane Doe | hockey
5. Jane Doe | basketball
etc. etc.
As you can see, the results returned need to be manipulated in order to produce the comma separated groups shown earlier, as .
Is there a simple way to get the page to display the groups so that they are in a comma separated list for each user in MySQL? Or do I have to write PHP code to loop through the results looking for duplicate IDs and generating the comma-separated lists of groups on the page? Or am I doing something completely wrong in my approach?
Many thanks.
There are a few options (in order of my personal preference).
Don't group by user id, and iterate trough your result and create an multi dimensional array using the user id as a key.
Use GROUP_CONCAT, which isn't pretty.
Use separate queries for selecting all groups + users, and iterate to create an multi dimensional array.
It makes no sense to have group_id in your user table if it is many-to-many and you already have a connecting table.
From PHP I guess you use MySQL, so you can use GROUP_CONCAT in situations like this.
Anyway, you are querying a hierarchical structure, which can not gracefully flatted to a single table, so you will always have to do some PHP coding to get the hierchical structure back.
try with GROUP_CONCAT with INNER JOIN
SELECT user.name, GROUP_CONCAT(group.name) FROM user
INNER JOIN user_group ON user.id = user_group.user_id
INNER JOIN group ON group.id = user_group.group_id
GROUP BY user.name
You're in luck. MySQL has a very handy aggregation operator group_concat which allows you to collapse the grouped results into a single row. In your case it would go something like this:
SELECT
`user`.name,
GROUP_CONCAT(`group`.group_name)
FROM `user`
INNER JOIN `user_group` ON (`user_group`.user_id = `user`.user_id)
INNER JOIN `group` ON (`group`.group_id = `user_group`.group_id)
GROUP BY `user`.name
This will match your table structure :)
SELECT `user`.name, GROUP_CONCAT( `group`.group_name )
FROM `user`
INNER JOIN `user_group` ON ( `user_group`.user_id = `user`.id )
INNER JOIN `group` ON ( `group`.id = `user_group`.group_id )
GROUP BY `user`.name
HTH :)

How to select a users specific info from a MySQL database?

I was wondering how can I have my users pick their favorite food from a category of foods in my MySQL database.
Will I need two different tables? If so what will my second table look like?
Here is my MySQL food table structure.
id | parent_id | food | url
You'll need 3 tables in total:
Food - holds food information
Users - holds users information
Users_Food - holds user id + food id (and maybe a ranking)
You should probably read up on database normalization.
You'd need to make a second table:
user_id | food_id
Make them both primary.
Then you can use JOIN's to select the food:
SELECT f.food, f.url
FROM user_food AS u
INNER JOIN food AS f ON (f.id = u.food_id)
WHERE u.user_id = {USER_ID}
This will give you a list of all favorite foods set by the user.

Categories