MySQL left join shows duplicate rows - mysql

I have two MySQL tables - 1) users and 2) warehouseMapping.
users
id, name
warehouseMapping
id, userId, warehouseId
From the above you can see that "warehouseMapping" table is the mapping table which will show that which warehouseIds are related to a particular user. There will be multiple warehouseIds for an user.
SELECT * FROM `users`
LEFT JOIN warehouseMapping
ON warehouseMapping.userId = users.id
WHERE 1 AND warehouseMapping.warehouseId IN (1, 2)
My intention is to show the users who have the warehouse id 1 and 2.
After submitting the same, MySQL showing me the same user name twice.
Inputs for users table:
id name
***************************
1 Niladri
2 Tanay
Inputs for warehouseMapping table:
id userId warehouseId
*****************************
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2

If you want to find users who have both warehouses, here is one way:
SELECT u.id, u.name
FROM users u
LEFT JOIN warehouseMapping w
ON w.userId = u.id
WHERE w.warehouseId IN (1, 2)
GROUP BY u.id
HAVING COUNT(DISTINCT w.warehouseId) = 2;

Related

MySQL join query on 3 tables [duplicate]

This question already has answers here:
Inner join with count() on three tables
(6 answers)
Closed 4 years ago.
user table:
id groupid username
1 1 user1
2 1 user2
3 2 user3
4 2 user4
group table:
id groupname
1 group1
2 group2
3 group3
sales table:
id userid amount
1 1 10
2 1 15
3 1 30
4 3 10
5 3 25
I like to know how many rows in sales table by groupid, not by userid. But sales table has no groupid field.
How can I join these 3 tables to get what I want? is this possible with one join query?
User INNER JOIN between the three tables based on the (foreign) key relationship between them, and use WHERE condition of groupid, to get results only for a specific $groupid
SELECT sales.* FROM sales
INNER JOIN user ON user.id = sales.userid
INNER JOIN group ON group.id = user.groupid
WHERE group.id = $groupid;
EDIT:
As asked further in the comments, to get Sum of sales for a particular groupid, we use SUM function. Here is the updated query:
SELECT SUM(sales.amount) AS total_sales FROM sales
INNER JOIN user ON user.id = sales.userid
INNER JOIN group ON group.id = user.groupid
WHERE group.id = $groupid;
You can just join two tables to get what you want:
select u.groupid, count(*) as count, sum(s.amount) as total
from user u
join sales s on s.userid = u.id
group by u.groupid;

How to get different results from one mysql table?

I have a user table in the database where all users of the system are stored.
The table has a user_id and a business_name and a first_name.
Some users are merchants and get a business name,
some users are consumers and get a first name.
In a second table I have transactions with a user_id and a merchant_id (which are defining the transaction) and an amount. Both ids reference to user table.
Table users:
user_id bus_name first_name role_id
1 Thomas 10
2 comp1 7
3 Peter 10
4 comp2 7
(role_id is defining with 10=consumer, 7=merchant)
Table transactions:
trans_id amount user_id merchant_id
1 12 1 2
2 23 3 2
3 34 3 4
4 19 1 4
Now I want to have a query with a result as one table:
This table should contain the transaction with amount, user_id, first_name, merchant_id and bus_name.
I want to get this result:
trans_id amount user_id first_name merchant_id bus_name
1 12 1 Thomas 2 comp1
2 23 3 Peter 2 comp1
3 34 3 Peter 4 comp2
4 19 1 Thomas 4 comp2
I have the problem that either I get only the first_name and empty bus_name or I get only the bus_name but empty first_name.
I am using a left join:
...
left join `users`
on(
(`transactions`.`user_id` = `users`.`user_id`)
)
...
But for this I would get for user_id=1 the first_name=Thomas and the bus_name='' would be empty because I only reference to one line in table and not also to different user with user_id=2.
But I want to say something like:
for trans_id=1
get first_name FROM users WHERE transactions.user_id = users.user_id
AND
get bus_name FROM users WHERE transactions.merchant_id = users.user_id
Thanks for your help, I tried so many things but it does not work.
You have to join the user table twice:
SELECT t.*, u.first_name, m.bus_name
FROM transactions t
JOIN users as u
ON t.user_id = u.user_id
JOIN users as m
ON t.merchant_id = m.merchant_id
you could use a duoble join in users table
select a.trans_id, a.amount , a.user_id, b.first_name, a.merchant_id, c. bus_name
from transactions a
inner join users b on a.user_id = b.user_id and b.role_id = 10
inner join users c on a.merchant_id = c.user_id and c.role_id = 7
To join the user table twice worked fine. With "left join users as consumer" I create a kind of a virtual users table called "consumer", this one is joined. Of course in select I had to adjust table name as well. Same for second "virtual" table od users, called "merchant".
select
`transactions`.`trans_id` AS `trans_id`,
`transactions`.`merchant_id` AS `merchant_id`,
`merchant`.`bus_name` AS `bus_name`,
`transactions`.`user_id` AS `user_id`,
`consumer`.`first_name` AS `first_name`,
`cards`.`card_id` AS `card_id`,
`cards`.`serial_no` AS `serial_no`
from (
`transactions`
left join `cards`
on(
(`cards`.`card_id` = `transactions`.`card_id`)
)
left join `users` as consumer
on(
(`consumer`.`user_id` = `transactions`.`user_id`)
)
left join `users` as merchant
on(
(`merchant`.`user_id` = `transactions`.`merchant_id`)
)
)

Mysql select 4 tables with 3 count

I have four tables
users
ID display_name
1 Name1
2 Name2
3 Name3
A user can add books to table books
books
book_id AddedByuserID
1 1
2 1
3 2
4 3
Also a user can add ebooks to table ebooks
ebooks
ebook_id AddedByuserID
1 1
2 2
3 2
4 3
Now a user can add books only to his collection (not ebooks)
collection
userID book_id
1 1
1 2
1 3
I need an output like this:
display_name books_added ebooks_added books_in_collection
Name1 2 1 3
Name2 1 2 2
Name3 1 1 1
This is what got:
SELECT users.*, COUNT(DISTINCT collection.book_id) AS books_in_collection, COUNT(DISTINCT books.AddedByuserID) AS books_added, COUNT(DISTINCT ebooks.AddedByuserID) AS ebooks_added
FROM users LEFT JOIN collection ON users.ID = collection.userID
LEFT JOIN books ON users.ID = books.AddedByuserID
LEFT JOIN ebooks ON users.ID = ebooks.AddedByuserID
GROUP BY users.ID
ORDER BY display_name ASC
The user display_name gets displayed correct and also the collection count, but the two other counts are showing 1.
If I remove DISTINCT the collection count says 86, and the two other counts show nothing.
I try to understand LEFT join and read tutorials but i'm stuck at the moment.
I would suggest correlated subqueries:
select u.*,
(select count(*) from collection c where u.id = c.userId) as books_in_collection,
(select count(*) from books b where u.id = b.AddedByUserId) as books_added,
(select count(*) from ebooks e where u.id = e.AddedByUserId) as ebooks_added
from users u;
I don't know why you are filtering out the third user, however.

How to join conditionally with different tables?

I am using MySQL.
I have three tables named ratings, users and one master table master_entityType.
Depending on the values from entityTable column of the master_entityType table, I have to join with another table. If the values from master_entityType is "Blogs", I have to join with blogs table. If the values from master_entityType is "items", I have to join with items table.
SELECT * FROM ratings AS r
LEFT JOIN users AS u ON u.userID = r.userID
LEFT JOIN master_entityType AS ms ON ms.entityTypeID = r.entityTypeID
CASE ms.entityTable
WHEN 'Blogs' THEN INNER JOIN blogs AS b ON b.blogID = r.entityID
END
WHERE r.entityTypeID = '10' AND r.entityID = '1' AND r.userID = '1'
While using the above query I am getting error, please suggest some step to get that query to work.
Structure of the table are as follows,
In users table,
UserID userName isActive
1 Dinesh 1
2 Kumar 1
In ratings table,
ratingID entityID entityTypeID userID rating
1 1 1 1 5
2 4 2 1 4
In master_entityType table,
entityTypeID entityTable entityTypeName entityTypeDescription active
1 blogs Blogs Null 1
2 items Items Null 1
In Items table,
ItemID name collection active
4 pencil 12 1
5 pen 06 1
In blogs table,
blogID name active
1 socail 1
2 private 1
Your design is strange, so performance is likely to be poor.
UNION ALL two tables together and join with the result. Something like this.
If MySQL has views, then create view that unions Items and Blogs table and use the view in other queries. It makes the queries easier to read, understand and maintain.
Here is SQL Fiddle. I adjusted the WHERE condition in the fiddle, because sample data doesn't have any rows with entityTypeID = 10.
SELECT *
FROM
ratings AS r
LEFT JOIN users AS u ON u.userID = r.userID
LEFT JOIN master_entityType AS ms ON ms.entityTypeID = r.entityTypeID
INNER JOIN
(
SELECT
ItemID AS EntityID
,'Items' AS EntityTypeName
,name
,active
FROM items
UNION ALL
SELECT
BlogID AS EntityID
,'Blogs' AS EntityTypeName
,name
,active
FROM blogs
) AS Entities ON
Entities.EntityTypeName = ms.entityTypeName
AND Entities.EntityID = r.entityID
WHERE r.entityTypeID = '10' AND r.entityID = '1' AND r.userID = '1'

Getting Average based on distinct row in mysql

I have a table users containing the fields userID,age,gender and i have another table
name as click_info containing fields(id,userID,clickID) The enrty in the click_info table are as following
id userID dubID
1 1 2
2 1 2
3 1 2
4 2 2
5 2 2
6 3 2
7 4 2
Now I want the average age of all the users who clicked on dubID 2 and i am using the following query
SELECT DISTINCT `dub_clickinfo`.`userID`, `users`.`age` AS `average`, `users`.*
FROM `dub_clickinfo` INNER JOIN `users` ON dub_clickinfo.userId = users.userID
WHERE (dubID=2)
The above query gives the incorrect average it will include the duplicate userID (like it will include userID 1 three times,2 two times) as well.
Please suggest a query
Thanks In Advance !!
Give it a try ,there is a one to many relation so you need to use left join not inner ,and apply a group function on user's id
SELECT dub_clickinfo.userID, users.age AS average, users.* FROM dub_clickinfo
LEFT JOIN users ON dub_clickinfo.userId = users.userID WHERE (dubID=2)
GROUP BY users.userID
try this
SELECT avg(age) FROM users WHERE userID in (select distinct userID from dub_clickinfo where dubID ='2')