SQL Select -> product -> comments -> user - mysql

thanks for yout time helping on this ;)
I'm new to SQL and wish to solve somethign in just one query and i dont know how to do it.-
Basically I've a table of products, a table of users and a table of comments, linked by products.id -> comments.pid and user.id -> comments.uid ,
i wish to know what is the best practice to create just 1 query and get all products with child comments, including username.

Learn about SQL joins:
SELECT *
FROM products
LEFT JOIN comments ON products.id = comments.pid
LEFT JOIN user ON user.id = comments.uid

learning joins is the best way to solve such a problem
Explanation
what we are trying here to do is create a virtual table which fetches records based on some relations.
I have created three tables here
product
user
comments
and there is a relation set between the
product and the comments table - using product.id and comments.prod_id
user and the comments table - using user.id and comments.user_id
Now you can use join to filter the results
SELECT product.id,user.name,comments.DATA
FROM comments
LEFT JOIN product ON comments.prod_id = product.id
INNER JOIN USER ON comments.user_id = USER.id;
or if you don't want to use join you can simply create a relation
but please do note that using joins is the best possible way to do it
SELECT product.id,USER.name,comments.DATA
FROM product,USER,comments
WHERE product.id = comments.prod_id AND USER.id = comments.user_id;
you can check the results here
SqlFiddle

Istead of using JOIN you can try this,
select p.id,u.name,c.data
from products as p,user as u,comment as c
where p.id = c.pid and u.id = c.uid;

Related

SQL statement from 2 tables

I am currently trying to run a sql statement to pull data from 2 tables I was wondering if someone could help me with my code. I would like to pull Project.Project_ID, Project.StartDate, Project.Users where Project_ID = 1 in both tables.
SELECT Project.Project_ID, Project.StartDate, Project.Users
FROM Project
INNER JOIN UserList ON Project.Project_ID=UserList.Project_ID
WHERE Project.Project_ID = '1';
I am not exactly sure what is your problem statement. If you can provide more details (DB Structure) that would be really helpful.
There could be more that one scenario you want to solve based on your data structure.
The only thing I see here is instead of Project.Users you should have UserList. Users. I assume User list tables having all the users details and it's not a pivot table. If it is then you need another join with User table.
SELECT
Project.Project_ID, Project.StartDate, UserList.Users
FROM
Project
INNER JOIN UserList ON Project.Project_ID=UserList.Project_ID
WHERE
Project.Project_ID = '1';
Please share your Database Structure.
With your model a user can only be linked to one project.
Below is with an joining table UserProject.
This way n users can take part to n projects. (n to n relation)
SELECT
p.id AS projectId,
p.startDate,
u.id AS userId,
u.name,
[...]
FROM
Project AS p,
UserProject AS up,
User AS u
WHERE
p.id = up.projectId
AND u.id = up.userId
AND p.id = 1;
And here is with a 1 to 1 relation
[...]
FROM
Project AS p,
User AS u
WHERE
p.id = u.projectId
AND p.id = 1;

What is the best way to implement a sql for retrieving multiple user names from same query?

I have a products table where I include 3 columns, created_user_id, updated_user_id and in_charge_user_id, all of which are related to my user table, where I store the id and name of the users.
I want to build an efficient query to obtain the names of the corresponding user_id's.
The query that I build so far is the following:
SELECT products.*,
(SELECT name FROM user WHERE user_id = products.created_user_id) as created_user,
(SELECT name FROM user WHERE user_id = products.updated_user_id) as updated_user,
(SELECT name FROM user WHERE user_id = products.in_charge_user_id) as in_charge_user
FROM products
The problem with this query is that if I have 30,000 records, I am executing 3 more queries per row.
What would be a more efficient way of achieving this? I am using mysql.
For each type of user id (created, updated, in_charge) you would JOIN the users table once:
SELECT
products.*,
u1.username AS created_username,
u2.username AS updated_username,,
u3.username AS in_charge_username,
FROM products
JOIN user u1 ON products.created_user_id = u1.user_id
JOIN user u2 ON products.updated_user_id = u2.user_id
LEFT JOIN user u3 ON products.in_charge_user_id = u3.user_id
This is the best practice method to obtain the data.
It is similiar to your query with sub-selects but a more modern approach which I think the database can optimize and utilize better.
Important:
You need foreign key index on all the user_id fields in both tables!
Then the query will be very fast no matter how many rows are in the table. This requires an engine which supports foreign keys, like InnoDB.
LEFT JOIN or INNER JOIN ?
As the other answers suggest a LEFT JOIN, I would not do a left join.
If you have an user id in the products table, there MUST be a linked user_id in the user table, except for the in_charge_user which is only present some times. If not, the data would be semantically corrupt. The foreign keys assure that you always have a linked user_id and a user_id can only be deleted when there is no linked product left.
JOIN is equivalent to INNER JOIN.
You can use LEFT JOIN instead of subselects.
Your query should be like:
SELECT
P.*,
[CU].[name],
[UU].[name],
[CU].[name]
FROM products AS [P]
LEFT JOIN user AS [CU] ON [CU].[user_id] = [P].[created_user_id]
LEFT JOIN user AS [UU] ON [UU].[user_id] = [P].[updated_user_id]
LEFT JOIN user AS [CU] ON [CU].[user_id] = [P].[in_charge_user_id]
First, your query should be fine. You only need an index on user(user_id) or better yet user(user_id, name) for performance. I imagine that the first exists.
Second, you can write this using LEFT JOIN:
SELECT p.*, uc.name as created_user,
uu.name as updated_user, uin.name as in_charge_user
FROM products p LEFT JOIN
user uc
ON uc.user_id = p.created_user_id LEFT JOIN
user uu
ON uu.user_id = p.updated_user_id LEFT JOIN
user uin
ON uin.user_id = p.in_charge_user_id;
With one of the above indexes, the two methods should have very similar performance.
Also note the use of LEFT JOIN. This handles the case where one or more of the user ids is missing.
Try this below query
SELECT products.*, c.name as created_user,u.name as updated_user,i.name as in_charge_user
FROM products left join user c on(products.created_user_id=c.user_id ) left join user u on(products.updated_user_id=u.user_id ) left join user u on(products.in_charge_user_id=i.user_id )
Also as Gordon Linoff mentioned create index on user table will fetch your data faster.

Joining one table all columns and second table few columns

I have two tables:- PERSON and DATA. What I want to do is fetch all details from PERSON table and only two columns from DATA table only when PERSON.personId = DATA.personId.
I am using this query:-
SELECT *
FROM PERSON AND SELECT DATA.value, DATA.field
FROM DATA where PERSON.personId = DATA.personId;
But I think this is wrong syntax. Can anyone tell me what is the right syntax for it.
SELECT p.*,d.column1,d.column2
FROM Person p
JOIN Data d
ON p.personId = d.personId
WHERE <Condition>
In this query person with all columns and data with your desire column you can fetch by this query.
Something like this:
select
P.*,
D.value,
D.field
from Person P
join Data D on P.PersonID = D.PersonID
change P.* to the specific columns that you need but P.* will get everything from the Person table.
check this post out LEFT JOIN vs. LEFT OUTER JOIN in SQL Server to learn about JOINS, the diagram is good to understand what the different ones do
Its really easy, Just execute this query:
SELECT
PERSON.*,
DATA.value,
DATA.field
FROM
PERSON INNER JOIN DATA USING (`personId`);
It selects all fields of PERSON + value and field from DATA.
Also it uses personId to join the two tables.
Fill free to ask if you need more info.
You can use join (LEFT JOIN)
SELECT * FROM PERSON LEFT JOIN DATA ON PERSON.personId = DATA.personId
Hope it will help you
Here's the correct syntax for achieving what you've asked for:
SELECT PERSON.column1,PERSON.column2,PERSON.columnN,DATA.value
FROM PERSON
INNER JOIN DATA
ON PERSON.personId = DATA.personId
Line#1: lists the columns that you want to select with references to their parent tables.
Line#2 and 3: are the two tables that you want to select from and join with
Line#4: is the join condition between the two tables (with matching IDs or other information)

MySQL saying that column is ambiguous

I need to do a query on the same field on a MySQL table but with different parameters. This is my query. The issue that comes up is that MySQL is saying that users_name is ambiguous.
SELECT projects_id,
projects_users_id,projects_companies_id,projects_name,
projects_description,project_registered_date,
projects_users_id_register,
users.users_name as userInCharge,companies.companies_name as company,
users.users_name as user_register FROM projects
LEFT JOIN users as userInCharge ON (users_id = projects_users_id)
LEFT JOIN users as register ON (users_id=projects_users_id_register)
LEFT JOIN companies ON (companies_id = projects_companies_id) ORDER BY projects_id DESC
My goal is to get the ID of both the person in charge of the project and the person who registered the project. How do I do this?
Your ambiguity is arising because of these LEFT JOIN clauses:
LEFT JOIN users as userInCharge ON (users_id = projects_users_id)
LEFT JOIN users as register ON (users_id=projects_users_id_register)
You need to specify where users_id is coming from (yes - I know they're from the same table, but SQL is a bit slow sometimes) Try:
LEFT JOIN users as userInCharge ON (userInCharge.users_id = projects_users_id)
LEFT JOIN users as register ON (register.users_id=projects_users_id_register)
Use the table alias and not users.users_name.
And also in the joins.
You JOIN with users table as userInCharge and register so use these names when You specify columns
userInCharge.users_name as userInCharge
register.users_name as user_register
instead of
users.users_name as userInCharge
users.users_name as user_register

Really simple MySQL JOIN not working?

What am I doing wrong? Seriously confused.
SELECT *
FROM photos
WHERE user_id = 1
JOIN photos_albums ON photos_albums.photo_id = photos.id
The context is, I have a table to store photos, and another table to store photo albums (not shown). I also have a cross-referencing table photos_albums to store which photos are in which albums.
I get given a Syntax Error. eh?
Thanks!
Jack
The WHERE clause must come after the joins, e.g.
SELECT *
FROM photos
INNER JOIN photos_albums
ON (photos_albums.photo_id = photos.id)
WHERE user_id = 1
See manual page for SELECT syntax for all the gory details.
The where should come at the end; try modifying it like this:
SELECT *
FROM photos p JOIN photos_albums pa ON pa.photo_id = p.id
WHERE p.user_id = 1