Exclude Staff Members - mysql

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;

Related

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

Adding Default Values on Joining Tables

I have the following tables:
Users
user_id course_id completion_rate
1 2 0.4
1 23 0.6
1 49 0.5
... ... ...
Courses
course_id title
1 Intro to Python
2 Intro to R
... ...
70 Intro to Flask
Each entry in the user table represents a course that the user took. However, it is rare that users have taken every course.
What I need is a result set with user_id, course_id, completion_rate. In the case that the user has taken the course, the existing completion_rate should be used, but if not then the completion_rate should be set to 0. That is, there would be 70 rows for each user_id, one for each course.
I don't have a lot of experience with SQL, and I'm not sure where to start. Would it be easier to do this in something like R?
Thank you.
You should first cross join the courses with distinct users. Then left join on this to get the desired result. If the user hasn't taken a course the completion_rate would be null and we use coalesce to default a 0.
select c.course_id,cu.user_id,coalesce(u.completion_rate,0) as completion_rate
from courses c
cross join (select distinct user_id from users) cu
left join users u on u.course_id=c.course_id and cu.user_id=u.user_id
Step1: Take the distinct client_id from client_data (abc) and do 1 on 1 merge with the course data (abc1) . 1 on 1 merge helps up write all the courses against each client_id
Step2: Merge the above dataset with the client info on client_id as well as course
create table ans as
select p.*,case when q.completion_rate is not null then q.completion_rate else 0
end as completion_rate
from
(
select a.client_id,b.course from
(select distinct client_id from abc) a
left join
abc1 b
on 1=1
) p
left join
abc q
on p.client_id = q.client_id and p.course = q.course
order by client_id,course;
Let me know in case of any queries.

How to use dictinct to get single record in many to one relation ship mysql

I have 2 tables like
user user_address
user_id name user_address_id city user_id address_type
1 abc 1 AAA 1 PRESENT
2 AAA 1 PERMANANT
I need query like
select user model1 , user_address model2 where model1.user_id = distinct model2.user_id
Because i know both addresses are same so i need only once.How i can get only one address.
Thanks in advance....
try put "group by" for a field on user_address, if they are the same anyway
select * from user_address inner join user as u on user_id = u.user_id group by city;
If i understood correctly what you need you can try this:
SELECT
*
FROM (
SELECT
user_id,
city ,
address_type
FROM
user_address
GROUP BY
user_id
) as tmp
INNER JOIN user
ON user.user_id = tmp.user_id

MySQL: Join based on multiple columns

I need to join table_1 and table_2 in MySQL and compare which user has the most winnings. Then update table_2.winner with the user id which has won..
table 1
city user winnings
1 a 99
1 b 0
1 c 50
1 d 2
table 2
city user_1 user_2 winner
1 a b a
1 c d 50
However I'm struggling to figure out how to join the tables thus far I have
SELECT table_1.winnings AS win_a, table_1.winnings AS win_b
FROM table_1, table_2
WHERE table_2.user_1 = table_1.user
AND table_2.user_2 = table_1.user
http://sqlfiddle.com/#!2/c855b/1
You can join against the table multiple times like this:
SELECT IF(user1.winnings > user2.winnings, "user1", "user2")
FROM table_2 games
JOIN table_1 user1 ON games.user_1 = user1.user
JOIN table_1 user2 ON games.user_2 = user2.user
http://sqlfiddle.com/#!2/c855b/16
I just used #skishore's query, a bit fixed, because it is broken for draws. The one that takes draws under consideration would be
SELECT
case when user1.winnings > user2.winnings then user1.user
when user2.winnings > user1.winnings then user2.user
else null
end
FROM table_2 games
JOIN table_1 user1 ON games.user_1 = user1.user
JOIN table_1 user2 ON games.user_2 = user2.user
But apart from this, I still don't get the purpose. I wrote this in comment to #skishore answer, but paste it here also. Consider the case:
User c won 99 matches played with user b, user d on the other hand won 2 matches played with user c. But who will be the winner between c and d? C
The second question is - why do you need this stored in a separate table? Winnings number will be dynamically changing so you would have to create trigger to keep winner column on table2 up to date. Can't you just get winner using this query?

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'