How to get different results from one mysql table? - mysql

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`)
)
)

Related

MySQL left join shows duplicate rows

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;

Count with Join in mysql

So I have this two table where it records what kind of food is the user's favorite:
users table
------------
id | country
------------
1 | US
2 | PH
3 | US
4 | US
5 | PH
food_favourites table
-----------------
food_id | user_id
-----------------
3 | 1
7 | 1
3 | 2
3 | 3
3 | 4
I want to know how many unique users from US tagged food_id 3 as their favorite.
So far I have this query:
select *, count(user_id) as total
from food_favourite
inner join users on users.id = food_favourites.user_id
where food_favourites.food_id = 3
and users.country = 'US'
group by users.id
Well This doesn't work coz it returns total to 4 instead of just 3.
I also tried doing subqueries - no luck, I think I'm missing something.
DROP TABLE IF EXISTS users;
CREATE TABLE users
(user_id SERIAL PRIMARY KEY
,country CHAR(2) NOT NULL
);
INSERT INTO users VALUES
(1,'US'),
(2,'EU'),
(3,'US'),
(4,'US'),
(5,'EU');
DROP TABLE IF EXISTS favourite_foods;
CREATE TABLE favourite_foods
(food_id INT NOT NULL
,user_id INT NOT NULL
,PRIMARY KEY(food_id,user_id)
);
INSERT INTO favourite_foods VALUES
(3,1),
(7,1),
(3,2),
(3,3),
(3,4);
SELECT COUNT(DISTINCT u.user_id) distinct_users
FROM users u
JOIN favourite_foods f
ON f.user_id = u.user_id
WHERE u.country = 'US'
AND f.food_id = 3;
+----------------+
| distinct_users |
+----------------+
| 3 |
+----------------+
First of all the answer to the above question should be 3 as id 1,3,4 all have food_id 3 as their favorite food.
To just print the query try this, it will surely work:
select count(*) as total from food_favourites
inner join users on users.id=food_favourites.user_id
where food_id=3 and country='US';
I want to know how many unique users from US tagged food_id 3 as their favorite.
You count unique values with COUNT DISTINCT:
select count(distinct ff.user_id) as total
from food_favourite ff
inner join users u on u.id = ff.user_id
where ff.food_id = 3
and u.country = 'US';
Don't group by user, because you don't want a result per user. You want one row with one number, telling you how many US users prefer food 3.
An alternative that I prefer over the join. The query reads like I would word the task: count users from US that like food 3.
select count(*) as total
from users
where country = 'US'
and id in (select user_id from food_favourites where food_id = 3);
No unnecessary join and hence no need to get back to distinct values.
The sub_query is
SELECT u.country, f.food_id, COUNT(u.id) AS 'Total users'
FROM users u
INNER JOIN food_favourites AS f ON (u.id = f.[user_id])
WHERE u.country = 'US'
GROUP BY u.country, f.food_id
select count(user_id) as total, Country
from food_favourites
inner join users on users.id = food_favourites.user_id
where food_favourites.food_id = 3
and users.country = 'US'
group by country
Untested, but I think this is what you're after? This will return results only for the US and a food id of 3. If you want something more reusable that you can simply loop through the results for ALL countries...something like this should work (once again, untested...):
select count(user_id) as total, Country, food_id
from food_favourites
inner join users on users.id = food_favourites.user_id
group by country, food_id
order by country, food_id
Try:
select count(user_id) as total
from food_favourites
inner join users on users.id = food_favourites.user_id
where food_favourites.food_id = 3
and users.country = 'US'

Exclude Staff Members

I have a user table:
id, userID, name, postcode
2 99 Bob AAA BBB
3 8384 Jim CCC DDD
And I have a user-keys table:
id, userID, keyID, val
1 435 3 1
2 773 8 0
3 99 2 1
4 99 5 1
5 99 2 1
Where keyID = 2 indicates that it is a staff member. I want to get all the userIDs from user table that are not staff members. So far I have the following SQL:
SELECT u.`userID` FROM `users` u
WHERE u.`userID` IS NOT NULL AND u.`userID` != 0;
However this does not exclude all users that have an entry in user-keys table with a keyID value of 2 and val of 1.
How can I perform this?
Edit: I neglected to state that any user may have multiple entries in the user-keys table, and I just want one list of userID from the user table, So really the results I am looking for from the above tables would simply be 8384.
You can try the following join query:
SELECT
t1.userID
FROM user t1
LEFT JOIN
(
SELECT DISTINCT userID, keyID -- you don't need DISTINCT here, but it may help
FROM `user-keys` -- and it makes the logic a bit clearer
WHERE keyID = 2
) t2
ON t1.userID = t2.userID
WHERE t2.userID IS NULL
The logic used here is that we retain all users from the user table who do not appear in user-keys with a keyID of 2, or who do not appear in user-keys at all.
Follow the link below for a demo in MySQL. Note that in some databases user-keys would not be a valid table name and would need to be escaped (I escaped above using backticks, SQL Server would use [user-keys], etc.).
Rextester
Update:
If you want to find only staff members, then the logic is much simpler. In this case, we can just INNER JOIN the two tables together and check the status of each user:
SELECT DISTINCT
t1.userID
FROM user t1
INNER JOIN `user-keys` t2
ON t1.userID = t2.userID
WHERE t2.keyID = 2
If you want the user with keyID <> 2 you should use a inner join
SELECT u.userID
FROM users u
and u.userID not in (select userID
from `user-keys`
WHERE keyID <>2 )
You can use below code
SELECT * FROM USER WHERE ID IN
(SELECT ID FROM USER_KEY WHERE KEY_ID <> 2);
If you need all columns you can use,
SELECT * FROM USER U
INNER JOIN USER_KEY UK
ON(U.ID = UK.ID)
WHERE UK.KEYID <> 2;

MySQL query, sum data from table

I have two table client and cash.
Table client:
ID Name ... other data
------------------------
1 Bob
2 Marry
3 Tom
Table cash:
ID Cash Id_client_fk
----------------------
1 500 1
2 500 3
3 500 3
4 500 1
I want to sum cash from every client, even if not exist in table cash.
The foreign key is id_client_fk to table client -> ID
You could use SUM() and a left join to achive this:
SELECT u.ID, u.Name, SUM(c.Cash) cash FROM client u
LEFT JOIN cash c ON c.Id_client_fk = u.ID
GROUP BY u.ID
To remove the NULL values you could use an IF statement:
SELECT u.ID, u.Name, SUM(IF(c.Cash > 0, c.Cash, 0)) cash FROM client u
LEFT JOIN cash c ON c.Id_client_fk = u.ID
GROUP BY u.ID
Not quite clear it. Please bring examples of data and what result you want. for example, just a few lines to understand the idea.
If I understand correctly, you need something like this:
SELECT client.id,client.name,s.sum_c FROM client INNER JOIN (SELECT `id_client_fk`, sum(`cash_row`) sum_c FROM `cash` GROUP BY `id_client_fk`) s ON client.id=s.id_client_fk ORDER BY 3 desc limit 20;

Select statement that that counts total number of distinct entries in one table, depending on data from another table

I have two tables: DATA and USERS
USERS
id sqft postal province city
==========================================================
1 1 Y7R BC Vancouver
2 2 Y7R BC Vancouver
3 1 L5B ON Toronto
and
DATA
id uid power
=======================
1 1 1000
2 2 1300
3 1 1500
uid in table DATA matches to id in table USERS
I want to be able to count the the number of distinct uid in DATA where the postal code is Y7R and sqft is 1
SELECT COUNT(id)
FROM `DATA` AS `d`
INNER JOIN `USERS` AS `u`
ON u.id=d.uid
WHERE u.postal='Y7R' AND u.sqft=1
GROUP BY u.id;
They should be distinct anyway if you have a proper schema, if so just remove the group by clause.
SELECT COUNT(DISTINCT D.UID) FROM DATA D
LEFT JOIN USERS U ON D.UID=U.ID
WHERE U.POSTAL='Y7R' AND U.SQFT=1)
In case you need distinct
You can use this solution:
SELECT COUNT(DISTINCT a.id)
FROM USERS a
JOIN DATA b ON a.id = b.uid
WHERE a.sqft = 1 AND
a.postal = 'Y7R'
Try this one:
SELECT COUNT(DISTINCT a.id)
FROM USERS a
INNER JOIN DATA b
ON a.id = b.uid
WHERE a.sqft = 1 AND
a.postal = 'Y7R'