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

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.

Related

Create relational tables or store serialized data in a column?

I have a users table with this structure:
user_id | name | email | mobile
And another table called products with this structure:
product_id | name | price
now I want to add wish list to my project, so that a user can add some products into his wish list (with his favorite categories. Exmaple: add a wish list category called my favorite clothes and add product_id = 55 to that category)!
Now I have 2 options:
1. Add another colum to users table called user_wish_list and then store serialized data in that column like below:
$user_wish_list = [
'user_category_1' => ['product_id_1', 'product_id_2', ....] ;
];
and store serialize($user_wish_list) in user_wish_list column.
2. create 2 tables as below:
tabe: wish_list_categories
user_id | category_id (PK) | category_title
and
tabe: wish_list_items
category_id (FK) | item_id | product_id (FK)
and finally create a relation between these tables (By SQL join)
which option is better? I personally think the second one!
one of the reasons for my choice is that I can access to data with pure SQL query
like below (I do not have to process data after fetching from database by using unserialize() ):
SELECT users.user_id, users.name, wish_list_categories.category_id,
FROM Orders
INNER JOIN Customers ON users.user_id = wish_list_categories.category_id
But what about other advantages?
Or let me ask a more general question: when we exactly use relational tables instead of use column? (consider one-to-one relationship)
Use tables. In general, don't store structured data in individual SQL values. Let the tables and foreign keys produce the structure you need.
your tables should be like:
1- users table:
user_id|user_name|Email|price
2- products table:
product_id|product_name|category_id|price
3- products_category
category_id|category_name
4- user_wish_list table:
user_id|product_id

GROUP_CONCAT with ordering and missing fields

I have a series of tables that I want to get rows returned from in the following format:
Student ID | Last Name | First Name | Quiz Scores
-------------------------------------------------
xxxxxxx | Snow | Jon | 0,0,0,0,0,0,0,0
There's 3 relevant tables (changing any existing DB structure is not an option):
person - table of all people in the organization
enrollment - table of student and faculty enrollment data
tilt.quiz - table of quiz scores, with each row storing an individual score
The tricky part of this is the Quiz Scores. A row for the quiz score only exists if the student has taken a the quiz. Each quiz row has a module, 1 - 8. So possible quiz data for a student could be (each of these being a separate row):
person_id | module | score
---------------------------
223355 | 1 | 100
223355 | 2 | 95
223355 | 4 | 80
223355 | 7 | 100
I need the quiz scores returned in proper order with 8 comma separated values, regardless if any or all of the quizzes are missing.
I currently have the following query:
SELECT
person.id,
first_name,
last_name,
GROUP_CONCAT(tilt.quiz.score) AS scores
FROM person
LEFT JOIN enrollment ON person.id = enrollment.person_id
LEFT JOIN tilt.quiz ON person.id = tilt.quiz.person_id
WHERE
enrollment.course_id = '$num' AND enrollment_status_id = 1
GROUP BY person.id
ORDER BY last_name
The problems with this are:
It does not order the quizzes by module
If any of the quizzes are missing it simply returns fewer values
So I need the GROUP_CONCAT scores to at least include commas for missing quiz values, and have them ordered correctly.
The one solution I considered was creating a temporary table of the quiz scores, but I'm not sure this is the most efficient method or exactly how to go about it.
EDIT: Another solution would be to execute a query to check for the existence of each quiz individually but this seems clunky (a total of 9 queries instead of 1); I was hoping there was a more elegant way.
How would this be accomplished?
There are some assumptions here about your data structure, but this should be pretty close to what you're after. Take a look at the documentation for GROUP_CONCAT and COALESCE.
SELECT `person`.`id`, `person`.`first_name`, `person`.`last_name`,
GROUP_CONCAT(
COALESCE(`tilt`.`quiz`.`score`, 'N/A')
ORDER BY `tilt`.`quiz`.`module_id`
) AS `scores`
FROM `person`
CROSS JOIN `modules`
LEFT JOIN `enrollment` USING (`person_id`)
LEFT JOIN `tilt`.`quiz` USING (`person_id`, `module_id`)
WHERE (`enrollment`.`course_id` = '$num')
AND (`enrollment`.`enrollment_status_id` = 1)
GROUP BY `person`.`id`
ORDER BY `person`.`last_name`
First thing to do is use the IFNULL() function on the score
Then, use ORDER BY inside the GROUP_CONCAT
Here is my proposed query
SELECT
person.id,
first_name,
last_name,
GROUP_CONCAT(IFNULL(tilt.quiz.score,0) ORDER BY tilt.quiz.module) AS scores
FROM person
LEFT JOIN enrollment ON person.id = enrollment.person_id
LEFT JOIN tilt.quiz ON person.id = tilt.quiz.person_id
WHERE
enrollment.course_id = '$num' AND enrollment_status_id = 1
GROUP BY person.id
ORDER BY last_name

MYSQL query to exclude records in specific condition

Hey I have the following MYSQL DB structure for 3 tables with many to many relation. Many users can have many cars and cars can be for many users as showing below:
Users
ID | Name
---------
100|John
101|Smith
Cars
ID | Name
---------
50|BMW
60|Audi
Users_cars
ID | UID | CID
---------
1| 100 |50
2| 100 |60
3| 101 |60
I have a page users_cars.php this page have two drop down lists
list of all users
list of all cars
In this page you can select a user from user's list and select a car from car's list then click add to insert into users_cars table.
What am trying to do is to exclude from user's drop down list all the users that have been linked with all the available cars from cars table.
In the example above user's drop down list will just have "Smith" because "John" linked with all cars available (BMW,AUDI), if "Smith" also has the BMW he will be excluded from the list. I need a select query for this condition and i don't want to use any nest select query to count user records inside users_cars table
If I understand what you are after you need to use GROUP BY in your query. So to select all users:
SELECT ID, UID FROM Users_cars GROUP BY UID
and for all cars:
SELECT ID, CID FROM Users_cars GROUP BY CID
That will group results that are the same, so you only get one instance of each user, or one instance of each car.
I hope I understood your question right.
I think you can so this using some programming -
With PHP/mysql -
Get count of all distinct car ID's
Get count of cars for each user. (making sure this lists only unique car ID's)
Loop through all users and in each loop compare the above two and exclude the user where this condition matches.
SELECT *
FROM users
WEHRE id NOT IN (SELECT uid
FROM (SELECT uid, COUNT(cid), COUNT(*)
FORM cars
LEFT OUTER JOIN users_cars ON cars.id = users_cars.cid
GROUP BY uid
HAVING COUNT(cid) = COUNT(*)
Basically, what you want to do is that (if I understood your problem) :
SELECT UID FROM Users_cars WHERE CID NOT IN (SELECT ID FROM Cars);
But carefull, this is a greedy request (depends on the size of the tables of course) and you should better put a flag on the user table and update then when your user uses the last available car (or with a batch) so you don't run the request too often !

MySQL Design Clarification

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.

Joining 2 Tables and show the same column repeatedly based on its associative ID

Hi i am not sure how to put this in a brief sentences, but i have DB table like the following
User Table
user_id
username
and so on...
Item
item_id
item_name
Item_Equipped
equipped_id head (FK to item_id)
hand (FK to item_id)
user_id (FK to user_id IN User Table)
I would like to generate a query that will display like the following format
user_id | head | head_item_name | hand | hand_item_name | ...
So far i only able to do this:
SELECT user.user_id, user.username,
equipments.head, equipments.head_acc,
equipments.hand,
equipments.acc, equipments.body
FROM gw_member_equipped AS equipments
LEFT JOIN gw_member AS user ON user.memberid = equipments.member_id
Which (i have to be brutally honest) doesn't do anything much.
I tried to perform INNER JOIN between item and item_equipped however i am unable to get individual name for each item (based on its item ID)
you need to join ITEM table two times with ITEM_EQUIPPED table.
you can use below query for your desired output column shown in question..
SELECT USER.User_Id,
Item_Equipped.Head,
Item_Heads.Item_Id Head_Item_Id, -- if you want you can remove this column
Item_Heads.Item_Name Head_Item_Name,
Item_Equipped.Hand,
Item_Hands.Item_Id Hand_Item_Id, -- and this column also as these columns are same as their previous select columns
Item_Hands.Item_Name Hand_Item_Name
FROM USER, Item Item_Heads, Item Item_Hands, Item_Equipped
WHERE USER.User_Id = Item_Equipped.User_Id
AND Item_Heads.Item_Id = Item_Equipped.Head
AND Item_Hands.Item_Id = Item_Equipped.Hand

Categories