MYSQL : Problem in writing where clause according to scenario - mysql

I have a DB (user_interests) set up with 3 fields: i_id (unique), interest_id, uid.
Then a second DB (interests) set up with the interests: interest_id (unique), interest_name
I'd like to do an SQL query to return a list of interests that two users have in common: User A (owner of a profile) and user B (you/viewer of a profile). I guess I need to query user_interests, then JOIN interests to get the name of the interest.
SELECT user_interests.i_id, user_interests.uid, interests.interest_name
FROM databases.user_interests
LEFT JOIN databases.interests
ON interest.interest_id = user_interest.interest_id
WHERE _______________
I'm confused about the where clause (if that is the correct way to do it at all). My goal is to get the interest_id from user_interests.interests where user_interests.uid is both A and then B (in separate rows).
I saw this link, but couldn't figure out what exactly I was missing: Group by x where y = A and B and C

I would solve it by joining two copies of user_interests, one which is filtered for user A (the profile owner), and one for user B, (the profile viewer).
SELECT *
FROM interests I
INNER JOIN user_interests A ON
A.interest_id = I.interest_id
AND A.user_id = {profile owner}
INNER JOIN user_interests B ON
B.interest_id = I.interest_id
AND B.user_id = {profile viewer}
Alternatively, more along the lines of the snippet you provided, you could complete the where clause with something like...
SELECT * FROM interests
WHERE interest_id in (SELECT interest_id
FROM users
WHERE user_id = A)
AND
interest_id in (SELECT interest_id
FROM user_interests
WHERE user_id = B)
Hope one of those works for you! Let me know if I can clarify

I don't think you need the where clause in this case just remove it and you will get the set of data you are looking for:
SELECT user_interests.i_id, user_interests.uid, interests.interest_name
FROM databases.user_interests
LEFT JOIN databases.interests
ON interest.interest_id = user_interest.interest_id

You may also create a where statement such as the following if you are looking to get a specific result set. I'm not discrediting the answer previously submitted, I am simply trying to help you with the specific WHERE statement you're looking for.
SELECT user_interests.i_id, user_interests.uid, interests.interest_name
FROM databases.user_interests
LEFT JOIN databases.interests
ON interests.interest_id = user_interests.interest_id
WHERE user_interests.uid IN ('A','B');
Please also note, that I changed your ON join to use interests and user_interests, with 's' appended to both, as those are the names of the table. They maintain the same schema name as they are assigned in the database.

Your query is correct remove the where part and run it. It will give you the same output as you need...

Related

SQL query that returns all the ids without a certain value

I have a table that maps User and Feature. Basically what features are enabled for each user. The table is |userId|featureId| with one(user) to many(feature) relationship.
I would like to create a query that takes a list of userIds and returns the list of userIds that are missing a specific feature.
Meaning I need to make sure that every id has a specific featureId.
userId featureId
1 A
1 B
2 A
3 C
4 D
3 A
So in this example, I'll get the list of ids (1, 2, 3, 4) and a featureId A and the query will return one row with userId 4 since it's the only userId with the feature A enabled.
To find a list of users that don't have feature X I would left join to the list of users that has that feature and return the ones not there. Like this:
SELECT *
FROM table_you_did_not_name as base
LEFT JOIN (
SELECT DISTINCT userID
FROM table_you_did_not_name
WHERE feature = 'X'
) as sub ON base.userID = sub.userID
WHERE sub.userID is null
I think I may have answered a different question: this doesn't address your data; but I'm unsure how you determine it is user 4 you want returned. as each user is missing some of the features the others have. Perhaps we just need to add a where clause below for the specific feature(A) in your example?
Think of data in terms of sets
You need
a set of data for all users (User or something)
a set of data for all features (feature)
and what features a user has (User_Feature)
Then you need to
Generate a set of every feature to every users (cross join)
Identify which of those the user has identified. (left join in user_feature)
and then only keep those where no feature has been identified (where no record in user_feature)
One method: This basically says return the features for each user that exist in a feature list, but have not been associated to a user.
SELECT U.userID, F.FeatureID as FeatureIDMissing
FROM USER U
CROSS JOIN FEATURE F
LEFT JOIN UserFeature UF
on U.UserID = UF.UserID
and F.FeatureID = UF.FeatureID
WHERE UF.UserID is null
-- and F.FeatureID = 'A' --maybe add this?
Alternate method: (combine two steps (2,3) by simply excluding those features which already exist for the user.
In english this says, return all the features for each user for which a user has not been associated
SELECT U.userID, F.FeatureID as FeatureIDMissing
FROM USER U
CROSS JOIN FEATURE F
WHERE not exists (SELECT *
FROM userFeature UF
WHERE U.UserID = UF.UserID
and F.FeatureID = UF.FeatureID)
--and F.FeatureID = 'A' --maybe add this?
Either answer should return the same results. It's a matter of preference database and performance .. Look at the execution plans to help decide which is best for you and your data.
Now maybe you mean you give a list of userID's you want to generate a unique set of features for all those users, and then return users w/o those features. If so instead of a cross join to feature you just need to use (Select distinct FeatureID from userFeatures where UserID IN ('yourListHere') this will generate a unique set of features for those users and identify which users are missing certain features shared with that set of users.
So...
SELECT U.userID, F.FeatureID as FeatureIDMissing
FROM USER U
CROSS JOIN (SELECT distinct FeatureID
FROM userFeatures
WHERE UserID IN ('yourListHere')F
LEFT JOIN UserFeature UF
on U.UserID = UF.UserID
and F.FeatureID = UF.FeatureID
WHERE UF.UserID is null
-- and F.FeatureID = 'A' --maybe add this?
as an example.

How can I filter out results based on another table. (A reverse join I guess?)

Basically, I have a table which contains two fields: [id, other] which have user tokens stored in them. The goal of my query is to select a random user that has not been selected before. Once the user is selected it is stored in the table shown above. So if Jack selects Jim randomly, Jack cannot select Jim again, and on the flip side, Jim cannot select Jack.
Something like this is what comes to mind:
SELECT * FROM users
WHERE (SELECT * FROM selected WHERE (id=? AND other=?) OR (id=? AND other=?));
Well, first of all I've read that uses sub-queries like this is extremely inneficient, and I'm not even sure if I used the correct syntax, the problem is however, that I have numerous tables in my scenario which I need to filter by, so it would look more like this.
SELECT * FROM users u
WHERE (SELECT * FROM selected WHERE (id=? AND other=?) OR (id=? AND other=?))
AND (SELECT * FROM other_table WHERE (id=? AND other=?) OR (id=? AND other=?))
AND (SELECT * FROM diff_table WHERE (id=? AND value=?))
AND u.type = 'BASIC'
LIMIT = 1
I feel like there's a much, much more efficient way of handling this.
Please note: I don't want a row returned at all if the users id is present in any of the nested queries. Returning "null" is not sufficient. The reason I have the OR clause is because the user's id can be stored in either the id or the other field, so we need to check both.
I am using Postgre 9.5.3, but I added the MySQL tag as the code is mostly backwards comptable, Fancy Postgre only solutions are accepted(if any)
You can left join to another table, which produces nulls where no record is found:
Select u.* from users u
left selected s on s.id = u.id or s.other = u.other
where s.id is null
The or in a join is different, but should work. Example is kinda silly...but as long as you understand the logic. Left join first table to second table, where second table column is not null means there was atleast one record found that matched the join conditions. Where second table column is null means no record was found.
And you are right...avoid the where field = (select statement) logic when you can, poor performer there.
Use an outer join filtered on missed joins:
SELECT * FROM users u
LEFT JOIN selected s on u.id in (s.id, s.other) and ? in (s.id, s.other)
WHERE u.id != ?
AND s.id IN NULL
LIMIT 1

Mysqli - AND OR

I have been trying to make my database show my contacts. But other users can give people access to their contacts (this is all stored in tblaccess)
I tried using this sql
SELECT *
FROM tblcontacts, tblaccess
WHERE (
tblaccess.user =1
AND tblaccess.contact = contactID
)
OR tblcontacts.userid =1
But it would only return a result if tblaccess has a row in.
The conditions are that if tblcontacts.userid <> 1
then check if tblaccess.user = 1
Thanks in advance
Here is the way that I'm understanding your question. You want all contacts where userid = 1, unless there is a record in tblaccess. If there is such a record, then the user column must be 1.
The following query implements this:
SELECT *
FROM tblcontacts c left outer join
tblaccess a
on a.contact = c.contactID
where c.userid = 1 and
(a.concatId is NULL or
a.user = 1
);
You shouldn't need to have too many conditionals - this is what JOINs are for. I believe that a RIGHT JOIN is what you're looking for. This is untested, but should return a NULL value on the right side if tablecontacts returns a userid 1 but tablecontacts does not have a userid.
SELECT *
FROM tblcontacts
RIGHT JOIN tblaccess ON tblaccess.user=tblcontacts.userid
WHERE tablecontacts.userid=1
UPDATE
Sounds like you are looking for two separate pieces of data from two separate tables. I know they are both IDs, but there is no foreign key to connect to in either table. In fact, the data in one table may well not be in another table. For this reason you will probably want to run a UNION query. That will allow you to pull anybody in either table that holds these values.
SELECT * FROM tblaccess WHERE user=1 AND contact = contactID
UNION
SELECT * FROM tblcontact WHERE userid=1
Alternatively, you could create a prepared statement or put the logic into your programming language.
A quick note - I would recommend explicitly calling your columns. Most people far more experienced than I would be hammering that home so figured I'd politely suggest it.
Try this:
SELECT *
FROM tblcontacts
WHERE tblcontacts.userid = 1
AND EXISTS (SELECT 1
FROM tblaccess
WHERE tblaccess.user = 1)

Need Help writing a MySQL query

I have a database with customer information, orders, etc. I need to run a query that returns all customers who have not placed an order at all.
Relevant tables: login and orders
Relevant Columns: login.loginID, login.loginFirstName, login.loginLastName, login.loginEmailAddress AND orders.OrderuserID
So essentially - in psuedocode: compare table login, column loginID for matches in the orders table under orders.OrderUserID. If no match exists (as in no orders placed) then output the users First Name, Last Name and Email address.
I have been racking my brain but having some real issues with the language. I'm a big time N00B when it comes to SQL.
Basically it'll look like that:
SELECT l.login_id
FROM login l
LEFT JOIN orders o
ON l.login_id = o.login_id
WHERE o.login_id IS NULL
The key is using LEFT JOIN with WHERE ... IS NULL condition. In other words, you specifically look for the rows in login table that don't have any information 'extended' within orders table.
That's just a general description, but I hope it should be helpful in your process of constructing the big query specific to your case. )
select loginFirstName, loginLastName, loginEmailAddress
from login
where loginID not in
(select distinct OrderuserID from orders)
You can also do it with a left join:
select loginFirstName, loginLastName, loginEmailAddress
from login left join orders on loginID = OrderuserID
where OrderuserID is null
Not sure which will execute faster; give it a try. The first is easier to understand, IMHO.
EDIT: "select distinct" means "return me the set of unique values of the field". So, the subquery in the first SQL returns the set of users (their IDs) who do have orders. If a user has multiple orders, DISTINCT makes sure her ID is returned only once.
This should do it:
select *
from login l
left join orders o on l.loginId = o.OrderuserID
where o.OrderuserID is null
Try:
select login.loginFirstName, login.loginLastName, login.loginEmailAddress
FROM login
LEFT OUTER JOIN orders ON login.loginID = orders.OrderuserID
WHERE orders.OrderuserID IS NULL;
or something like that. I suspect the trick for a newer SQL user is the LEFT OUTER join. Without that specifier, a join will only return rows from the first table IF there are matches in the second. This way you get them all (and then filter out matches with the IS NULL phrase).
Though you should try first yourself and you could search on google first :):) .
Anyways you can use it in this way,
SELECT l.loginFirstName,l.loginLastName,
l.loginEmailAddress FROM login AS l LEFT JOIN orders as o
ON l.loginID = o.OrderuserID where OrderuserID is NULL

mysql: two tables but three select criteria

I have two tables: users and user_depts. Let's say (for this question) that users only has an 'id' column, and user_depts has 2: 'uid' and 'did'.
I am looking for an SQL line that will return all the user IDs for all the departments with which a given user ID (let's say 7, though this'll come dynamically from PHP) is associated.
What I've tried is:
SELECT id FROM users, user_depts
WHERE users.id = user_depts.uid
AND user_depts.uid = 7
But of course this does nothing but return 7. I think I might have to join the table to itself, but I only know the shortcut syntax for joining, and it doesn't seem to be sufficient. Any pointers would be greatly appreciated!
Use EXISTS:
SELECT uid FROM user_depts
WHERE EXISTS (
SELECT * FROM user_depts a
WHERE uid = 7 AND a.did = user_depts.did
)
I am looking for an SQL line that will return all the user IDs for all
the departments with which a given user ID (let's say 7, though
this'll come dynamically from PHP) is associated.
If this means you want to find all the users with the userid: 7 that has a user_departent connected to it this is your query:
select users.id from users
inner join user_depts.uid = users.id
where users.id = 7
select uid from user_depts where did
in (select did from user_depts where uid=7)
First select all the did with which a user is associated using subquery
Then select all the user_id for the selected departments.
It's the best way you can do it.
and if you want to remove repeated result then you can use distinct