MYSQL compare values from same columns - mysql

Okay I tried to look all over stackoverflow, and the closest solution I found is this:
mysql AND clause on same column multiple times
But I can't use statements and "having" syntax won't work because of group by. There MUST be a simple solution to this.
The 2 tables looks like this (simplified):
users:
uid name
1 person 1
2 person 2
3 person 3
categories:
uid value
1 actor
1 musician
2 actor
3 dancer
4 musician
4 dancer
I want to get the uid of those that are 2 values at the same time. For example, I want to get the UID that is an actor AND a musician. Not just one value, but both of them must be required!
First I tried this:
SELECT users.uid, users.name
FROM
users
LEFT OUTER JOIN categories ON users.uid = categories.uid
WHERE (categories.value = 'actor' AND categories.value = 'musician')
GROUP BY u.uid;
This of course does not work since one row can't have 2 values.
Does anyone know a solution?

You can JOIN to the categories table multiple times to get the result:
SELECT users.uid, users.name
FROM users
INNER JOIN categories c1
ON users.uid = c1.uid
INNER JOIN categories c2
ON users.uid = c2.uid
WHERE c1.value = 'actor'
AND c2.value = 'musician';
See SQL Fiddle with Demo

SELECT users.uid, users.name
FROM users
LEFT JOIN categories ON users.uid = categories.uid
WHERE categories.value in ('actor', 'musician')
GROUP BY u.uid, users.name
having count(distinct categories.value) = 2;

Use a having clause
SELECT u.uid, u.name
FROM users u
LEFT OUTER JOIN categories c ON u.uid = c.uid
WHERE c.value = 'actor' OR c.value = 'musician'
GROUP BY u.uid
having count(distinct c.value) > 1

If you really do not want to use having you could try this:
SELECT uid, name
FROM users
WHERE
uid IN (SELECT uid FROM categories WHERE value='actor')
AND uid IN (SELECT uid FROM categories WHERE value='musician')
But there is really nothing wrong with using HAVING ;)

Related

struggling with a sql query join

I am struggling with writing a query join in mysql
I have two table
Challenges
challenge_ID(int) |to_user(int)|from_user(int)|timestamp|gameID=>nullable
Users
iduser(int)|first_name(string)
I want get the first name of to_user and form_user when I have the challengeID
for instance if
Challenges
challenge_ID(int) |to_user(int)|from_user(int)|timestamp|gameID
1 9 10 sometimestamp
Users
iduser(int)|first_name(string)
9 Tom
10 Chris
11 Patrick
I would like to get 'Tom' and 'Chris' for challenge id 1
Thanks for your help.
It may be something like this:
SELECT first_name
FROM Users
WHERE iduser IN (SELECT to_user
FROM challenges
WHERE Challenge_Id = 1
UNION
SELECT from_user
FROM challenges
WHERE Challenge_Id = 1)
this is how you do this
select c.* ,u.first_name as to_name , u2.first_name as from_name
FROM challenges c
join users u on c.to_user = u.id
join users u2 on c.from_user = u2.id
where c.challenge_ID = 1
It looks like you need a UNION and then a JOIN:
SELECT users.first_name
FROM (
SELECT from_user AS usr FROM challenges WHERE challenge_id=1
UNION
SELECT to_user FROM challenges WHERE challenge_id=1
) u INNER JOIN users ON u.usr = users.id_user
UNION will remove duplicates on the subquery, if there are no duplicates you can use UNION ALL which is faster.
You can try this query
SELECT u_to.first_name, u_from.first_name
FROM challenges c
INNER JOIN users u_to ON u_to.iduser = c.to_user
INNER JOIN users u_from ON u_from.iduser = c.from_user
WHERE c.challange_ID = 1

Output Name Field is DIfferent With the Output without Name Field MYSQL

SELECT users.id as uid, projects.id as pid
FROM users
inner join usergroup on usergroup.id = users.user_group
inner join bookings on bookings.agent_id = users.id
inner join units on bookings.unit = units.id
inner join types on types.id = units.types_id
inner join projects on projects.id = types.project_id
WHERE bookings.status = 'Accepted' AND units.status = 'Sold'
GROUP BY pid
with the query above, i get the correct and logic output:
pid | uid
1 1
2 1
9 12
10 14
then i want to show the user's name, so i added 1 field in query as shown below:
SELECT users.id as uid, users.f_name, projects.id as pid
FROM users
inner join usergroup on usergroup.id = users.user_group
inner join bookings on bookings.agent_id = users.id
inner join units on bookings.unit = units.id
inner join types on types.id = units.types_id
inner join projects on projects.id = types.project_id
WHERE bookings.status = 'Accepted' AND units.status = 'Sold'
GROUP BY pid
but i got a different output for uid:
pid | uid
1 1
2 1
9 9
10 11
This is not logic and anyone know why? Let's assume both are correct but why will output different result?
Your 2nd query you are filtering data with join condition before where condition while in 1st query you are filtering data just in where clause...keep you 2nd query same as 1st to get same results....
try below query-
SELECT projects.id as pid, users.id as uid, users.f_name
FROM users
inner join usergroup on usergroup.id = users.user_group
inner join bookings on bookings.agent_id = users.id
inner join units on bookings.unit = units.id
inner join types on types.id = units.types_id
inner join projects on projects.id = types.project_id
WHERE bookings.status = 'Accepted' AND units.status = 'Sold'
GROUP BY pid
One project ID can be associated to many units and each unit with many bookings and hence with many users. You group by project ID, but you don't specify which of all associated users you want to see for a project ID. You would do this with an aggregate function such as MIN(users.id), MAX(users.id), etc. But you don't use such function, thus telling MySQL: "just give me randomly one of the matching users".
As long as you keep your query as is, it seems that MySQL always gives you the same users, maybe the first it finds. This is by no way guaranteed; you could just as well get different users with the same query.
Now that you changed your query, MySQL goes another route and picks different matching users.

MySQL select query from two tables

I have two tables: users and works
I need write select query for count different names from users table where work_status = 1 from works table
The total is: 3 John, 1 Tom
I need get result:
John 2 (2 because one John work_status = 0 ant this not counting)
Tom 1
I have write select that can count different names, just need compared work_status..
SELECT name,COUNT(*) as num FROM users GROUP BY name
My query return:
There is a problem in your question. So here you have two solutions.
If there are three different John working on the company, this is your query
SELECT u.name, COUNT(*) as num
FROM users u INNER JOIN works w ON w.user_id = u.id
WHERE w.work_status = 1
GROUP BY u.name, u.id
If there are only one John working in the company, your query is this one:
SELECT u.name, COUNT(*) as num
FROM users u INNER JOIN works w ON w.user_id = u.id
WHERE w.work_status = 1
GROUP BY u.name
Note: If three John are the same person, you should delete the 2 last and on the works table change user_id = 3 and user_id = 4 for user_id = 1
This is a simple JOIN query:
SELECT u.name, COUNT(*) num
FROM users u
JOIN works w
ON w.user_id = u.id
AND w.work_status = 1
GROUP BY u.name
This one should do the job:
SELECT users.name,SUM(works.work_status) as num
FROM users,works
WHERE users.id=works.id
GROUP BY name
SELECT
users.`name`,
COUNT(*) num
FROM
users,
works
WHERE users.`id` = works.`user_id`
AND works.`work_status` = 1
GROUP BY users.`name` ;

User CASE or subquery?

I have 3 tables: tickets, tickets_users and users. My problem is that in the users table I have 2 types of users: requesters and solvers: type 1 and 2.
I want to select the ticket, requester (if any, can be multiple) and solver (if any, can be multiple).
I'm thinking something in the lines of:
SELECT
t.id, t.description,
(u.id where u.type = 1) AS requester,
(u.id where u.type = 2) AS solver
FROM
tickets t
INNER JOIN
tickets_users tu ON t.id = tu.ticket_id
INNER JOIN
users u ON tu.user_id = u.id
Obviously this does not work.
The tables look like this:
Tickets:
ID Description
1 Description 1
2 Description 2
Tickets_users
ID Ticket_ID User_id Type
1 3 4 1
2 5 8 2
Users
ID Name
1 John
2 Mary
Thanks,
In the meantime I think I found a solution using a sub-query in the join clause, but to me it looks rudimentary:
SELECT
t.id, t.name AS ticket_name, type1.users_id AS requester,
type2.users_id AS solver
FROM
tickets t
INNER JOIN
(SELECT users_id, tickets_id
FROM tickets_users
WHERE TYPE = 1) type1 ON t.id = type1.tickets_id
INNER JOIN
(SELECT users_id, tickets_id
FROM tickets_users
WHERE TYPE = 2) type2 ON t.id = type2.tickets_id
Should be something like this.
SELECT
t.id, t.description, u.id, userType
CASE WHEN u.type = 1 THEN 'requester' ELSE 'solver' END
FROM
tickets t
INNER JOIN tickets_users tu ON t.id = tu.ticket_id
INNER JOIN users u ON tu.user_id = u.id
Please provide sqlfiddle in case above example does not work.
With Joins,
SELECT
t.id, t.description, requesters.id, solvers.id
FROM
tickets t
INNER JOIN tickets_users tu ON t.id = tu.ticket_id
LEFT JOIN users requesters ON (tu.user_id = requesters.id AND requesters.type=1)
LEFT JOIN users solvers ON (tu.user_id = solvers.id AND solvers.type=2)
As you can tell, users table is joined twice (as requesters and as solvers with additional conditions). The reason LEFT JOIN is used is because if there's a record with no requesters or no solvers, INNER JOIN would completely ignore the whole record until it has a requester and a solver.

Joining 3 Tables With Multiple Column Connections

I am struggling to get the correct syntax for what I need and wondered if anyone could help?
I have 3 tables: users, owneditems and shopitems
From users I need to get userid and city
From owneditems I need to get userid and itemid
From shopitems I need to get id and city
userid on owneditems and users will be the same
itemid on owneditems will be the same as id on shopitems
city on shopitems and users will be the same
What I'm after is to find out which city the users are in and tie up which items they own in that city.
The syntax I tried using was
SELECT users.city, users.id, shopitems.city, shopitems.id, owneditems.itemid, owneditems.userid
FROM users, shopitems, owneditems
WHERE users.city = shopitems.city
AND owneditems.itemid = shopitems.it
AND users.id = owneditems.userid
It is not exactly clear what you are trying to do, but have you tried using a LEFT JOIN instead of the INNER JOIN:
select u.city,
u.id,
s.city,
s.id,
o.itemid,
o.userid
from users u
left join owneditems o
on u.id = o.userid
left join shopitems s
on u.city = s.sity
and o.itemid = s.itemid