I have two tables and they are as follows:
USERS
ORDERS
I want select all users who have at least 1 order or more in the ORDERS table. I know there is an inline query for this in MySQL, but right now I have to select all users and then make another query seeing if each user has an order - all this using a PHP loop.
What I am doing now is not ethically correct, so I basically just want to select all users who have been referenced in the ORDERS table in ONE MySQL query.
This is a query you should be using
select distinct u.* from users u
inner join orders o on o.user_id = u.id;
Note the distinct and u.*. This query will not select fields from orders and it will not select the same user twice (if one has more than one order).
Demo: http://sqlfiddle.com/#!2/6ebcc/3
You can use mysql join syntax. Assuming both of your tables has userid column, this is the example :
SELECT * FROM USERS a JOIN ORDERS b ON
a.UserId = b.UserId
This is a simple database operation, see here for the explanation join
Related
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.
I have to tables: user and userimages.
Right now, I'm using the following query:
SELECT * FROM users u INNER JOIN userimages ui ON u.id=ui.userid;
Yes. It retrieved the records if the userid and id is equal. What I really want to do is to select all records from table users even if its id is not present on the second table (userimages)
My question is how to select all records in the users table with or withou userid on the second table?
You're looking for a LEFT JOIN, which will pull all rows from the first table and join where applicable to the right.
SELECT * FROM users u LEFT JOIN userimages ui ON u.id=ui.userid;
I have a table with orders and a table with users. It's possible for an order to be placed with an entry in the user table.
With the following MySQL statement I get duplicate values for orders if there is a matching user:
SELECT o.id, u.id as 'user_id', u.name
FROM orders o
LEFT JOIN users u ON o.user_id = u.id
WHERE o.status = 'active'
If I add a GROUP BY o.id it solves the issue.
SELECT o.id, u.id as 'user_id'
FROM orders o
LEFT JOIN users u ON o.user_id = u.id
WHERE o.status = 'active'
GROUP BY o.id
It also works if I use SELECT DISTINCT.
My questions are:
Why does it return duplicate fields?
Is it more correct to use GROUP BY or SELECT DISTINCT?
Your detail query -- the query returning every row, rather than the deduplicated version with DISTINCT or GROUP BY -- is finding more than row in users matching each row in orders. So, it is dutifully returning all those rows.
To solve your problem correctly you need to figure out why there are multiple users rows for each order. That is, for some values of order.user_id there are multiple values of users.id.
That seems a little strange to me, but I do not understand your data model. You probably need to get to investigate this data anomaly. A conventional schema would have each user able to place multiple orders, but each order relating to only one user. In that schema this query would yield one row per order but still include users with no orders:
SELECT u.id AS user_id, o.id AS order_id
FROM users AS u
LEFT JOIN orders AS o ON o.user_id = u.id
Could it be that is what you want?
Contrary to some peoples' belief, GROUP BY orders.id and SELECT DISTINCT orders.id, users.id are not the same thing. In fact, your proposed use of GROUP BY misuses the notorious MySQL extension to GROUP BY. Standard SQL will reject your GROUP BY. It will only accept GROUP BY orders.id, users.id, which is indeed equivalent to DISTINCT.
Why does it return duplicate fields?
It returns duplicates because you have not applied anything to stop it from doing so. When you apply GROUP BY or DISTINCT then you actually stop the duplicates.
Is it more correct to use GROUP BY or SELECT DISTINCT
Both are equivalent and can be used as per your convenience. You may find that DISTINCT is faster over GROUP BY under the fact that indexes are not created on your table. But that does not make the usage of GROUP BY incorrect. If indexes are created then they both are equivalent to each other.
Your query does not need a JOIN at all. You can just use:
SELECT o.id, o.user_id
FROM orders o
WHERE o.status = 'active';
As for SELECT DISTINCT or GROUP BY. The two should be equivalent in performance (or very close). They are doing essentially the same work.
The advantage of GROUP BY is that you can add aggregation functions. The advantage of DISTINCT is that you don't have to list all the columns twice, and it accepts *.
It's been so long since I did any Mysql queries I forgot how to do basic joins. I have two tables:
Orders_ and
Members
I need to create one view which displays all the orders with the associated Email and Member_Id.
http://i.imgur.com/7ttXtrk.png <-- Tables
The query, based on your image, should look like so:
SELECT Orders.*, Members.*
FROM Orders
INNER JOIN Members ON Orders.coordinateList_Id = Members.Members_Member`
I would refer to the MySQL reference
SELECT *
FROM Orders
INNER JOIN Members
ON Orders.coordinateList_Id = Members.Members_Member
So I have 2 tables in a MySQL database, one for "Users" and the other for "Orders", where each entry in Orders is an order placed by a User (Some users can have multiple orders, while some might not have any). I am working on reporting queries and one of the reports I want is a list of Users that have never placed any orders. I am still a bit of a beginner when it comes to MySQL queries, so I am not sure how to do this one. The query will be placed via PHP if that makes any difference.
Here are my columns in each table (simplified):
Users:
ID
Name
Orders:
OrderID
OrderName
CustomerID (corresponds to User.ID that placed the order)
Any help here would be great. Thanks!
Use a LEFT JOIN on Orders and check whether OrderId is null:
SELECT U.*
FROM
Users U
LEFT JOIN Orders O ON(U.ID = O.CustomerID)
WHERE
O.OrderId IS NULL
SQLFiddle
SELECT ID, Name
FROM users
WHERE ID NOT IN (SELECT DISTINCT customerID FROM Orders)
So basically you'are looking for orders that are not made by that user
Select * from Orders where CustomerID = 5 //5 is the id of the custumer
If you are doing a search by name
Select * from Orders LEFT JOIN Users on Users.ID Where Users.name ='Mark'
If no results, it mean that customer never ordered anything
Try
SELECT U.*
FROM Orders a
RIGHT JOIN Users b
ON b.ID = a.CustomerID
WHERE a.OrderId IS NULL