Get users from two tables where id's are not the same - sql

I ran across on a pretty though query for Rest API. Want to hear your recommendations.
Now I have two tables :
Company Users: which stores major information about the registered users like:
id, name, email, phone number.
Matching_users: which stores the information like:
active_user_id, matching_user_id where active user id is the authorized user ID, and matching user id is the any other user id which Authorized user have met before.
The question is: how I could execute the query where I would be able to fetch all other users (except authorized user ID, and users with whom authorized user would have met before )?
For example:
TABLE : company_users
ID | NAME | EMAIL
1 | Jake | jake#gmail.com
2 | Jane | jane#gmail.com
3 | Jacob | jacob#gmail.com
4 | June | june#gmail.com
and
TABLE : matching_table
ID | ACTIVE_USER_ID | MATCHING_USER_ID
1 | 1 | 2
How can I execute for authorized user only users from company_userswith id 3 and 4?

Get all rows of table 2 :
$matching_rows = MatchingTable::all();
$active_users = $matching_rows->pluck('active_user_id')->toArray();
$matching_users = $matching_rows->pluck('active_user_id')->toArray();
Merging them together :
$auth_users = array_merge($active_users, $matching_users);
Using whereNotIn :
$unauth_users = Users::whereNotIn('id', $auth_users)->get()`

Please try this.
If Except ACTIVE_USER_ID Then
Select * from company_users
Where Id NOT IN ( SELECT Distinct ACTIVE_USER_ID FROM matching_table)
If Except MATCHING_USER_ID Then
Select * from company_users
Where Id NOT IN ( SELECT Distinct MATCHING_USER_ID FROM matching_table)
If Except ACTIVE_USER_ID and MATCHING_USER_ID Then
Select * from company_users
Where Id NOT IN ( SELECT Distinct MATCHING_USER_ID FROM matching_table)
AND Id NOT IN ( SELECT Distinct ACTIVE_USER_ID FROM matching_table)

Related

SQL Query to show results that don't have a relation to variable

For an assignment I have which includes a delete and add friend system (like Facebook), I've made a query that works by using two SQL tables, one which includes a friend_id, name and other information, and another which holds two friend_id columns, that show the relationship with the users and if they're friends.
User Table (friends)
| friend_id | profile_name |
|:---------- |:------------:|
| 1 | John |
| 2 | Peter |
| 3 | Alex |
| 4 | Nick |
---------------------------
Friendship Table (myfriends)
| friend_id1 | friend_id2 |
|:---------- |:----------:|
| 1 | 3 |
| 2 | 4 |
| 3 | 1 |
| 4 | 2 |
-------------------------
I am wanting to get a query which selects people that don't have a connection with a result (I want to show anyone who doesn't have a connection to friend_id '1', so only want to show users 2 and 4), and then display their name.
I have a query that selects the ones which have the relation which is:
SELECT friends.profile_name,friends.friend_id FROM `myfriends` JOIN `friends` ON friends.friend_id = myfriends.friend_id2 WHERE `friend_id1` = 1;
The query bellow shows all results from the table, and even using '!=', it doesn't select those who don't have a relation to friend_id '1'
SELECT friends.profile_name,friends.friend_id FROM `myfriends` JOIN `friends` ON friends.friend_id = myfriends.friend_id2 WHERE `friend_id1` != 1;
How can I fix this query so it shows all results but those connected to ‘friend_id1’ = 1
with connected as (SELECT friend_id,
myfriends.friend_id2 friend
FROM myfriends
JOIN friends
ON friends.friend_id = myfriends.friend_id1
WHERE friend_id1 = 1)
select *
from friends
where friend_id not in (select distinct friend from connected union all select distinct friend_id from connected)
you cannot change the where clause as it specifies which user you want to focus on.
So first get the users that are connected (in the first cte), and then select all users except those found in the first result of the connected users.
By the way, your example is misleading as it can be solved with a bug by doing something simple in the join.
edit
while it wasn't clease which version you were using, (I thought with clause is available in the newer mysql versions) I created another solution that is working on mysql 5.6 and should work for you as well:
select f.*
from friends f
left join (
SELECT friend_id, myfriends.friend_id2 friend
FROM myfriends
JOIN friends
ON friends.friend_id = myfriends.friend_id1
WHERE 1 in (friend_id,friend_id2)) f1
on f1.friend = f.friend_id
where f1.friend is null
it has a nicer implementation in one part (1 in one of 2 columns), and uses a left join that takes the nulls from the right table.

Selecting all elements that only one of their associated value is not in a predefined list

Note: I had a hard time choosing a title for this question. I am not sure it describes accurately what I want, so I will be grateful if instead of a downvote you will help to improve the title. :)
I have a table with the following structure:
log:
+-----+-----+
| uid | uip | <- user id and user ip
+-----+-----+
I also have a table with some predefined user id's:
predfined_users:
+-----+
| uid |
+-----+
| 1 |
-------
| 2 |
-------
| 3 |
-------
What I am trying to achieve:
My "algorithm" should find all the uip that the result of the following steps for them is 1:
Collect from log all distinct users which are associated with the uip
Count how many of the users are NOT in the predfined_users table.
Example:
Let's say this is the list of the users that are associated with the IP address 1.0.0.0:
+-----+
| uid |
+-----+
| 1 |
-------
| 3 |
-------
| 7 |
Only one of these values is not in predfined_users (7), so 1.0.0.0 should be returned. I want to select all the uip that satisfy this as well, meaning, only one of the uid associated with them is not in predfined_users. Also, it is worth noting that if a uip is associated only with one uid, then the query should not return it.
What I have already tried
Here is my general idea but I am not sure what to write instead of the ??? or even if I am in the right direction:
SELECT [uip]
FROM log
WHERE (
SELECT COUNT(*)
FROM (
SELECT DISTINCT [uid]
FROM log WHERE [uip] = ???
)a
WHERE uid NOT IN (
SELECT uid
from predfined_users
)
)=1
Something like this:
select l.uip, count(distinct l.uid)
from log l left join
predefined_users pu
on l.uid = pu.uid
where pu.uid is null
group by l.uip;
You can use this query to retrieve the uips that having only one associated uid which does not exist in table predfined_users:
Select distinct uip from [dbo].[Log]
where uid not in(Select uid from predfined_users)
group by uip
having count(uip) = 1
if you want to retrieve the uips which have associations which do not exist, regardless of the count of irrelevant uids, you can use this code:
Select distinct uip from [dbo].[Log]
where uid not in(Select uid from predfined_users)

Beginner SQL query with ROW_NUMBER

i'm kind of a beginner with SQL.
Right now i'm trying to create a bit complex select but i'm getting some error, which I know it's a beginner mistake.
Any help appreciated.
SELECT ROW_NUMBER() OVER (ORDER BY score) AS rank, userID, facebookID, name, score FROM (
SELECT * FROM Friends AS FR WHERE userID = ?
JOIN
Users WHERE Users.facebookID = FR.facebookFriendID
)
UNION (
SELECT * FROM User WHERE userID = ?
)
Where the 2 ? will be replaced with my user's ID.
The table User contains every user in my db, while the Friends table contains all facebookFriends for a user.
USER TABLE
userID | facebookID | name | score
FRIENDS TABLE
userID | facebookFriendID
Sample data
USER
A | facebookID1 | Alex | 100
B | facebookID2 | Mike | 200
FRIENDS
A | facebookID2
A | facebookID3
B | facebookID1
I'd like this result since Alex and mike are friends:
rank | userID | facebookID | name
1 | B | facebookID2 | Mike
2 | A | facebookID1 | Alex
I hope this was quite clear explanation.
I'm getting this error at the moment:
Error occurred executing query: Incorrect syntax near the keyword 'AS'.
You've got several issues with your query. JOINS come before WHERE clauses. And when using a JOIN, you need to specify your ON clauses. Also when using a UNION, you need to make sure the same number of fields are returned in both queries.
Give this a try:
SELECT ROW_NUMBER() OVER (ORDER BY score) AS rank, userID, facebookID, name, score
FROM (
SELECT *
FROM Users
WHERE UserId = 'A'
UNION
SELECT U.userId, u.facebookId, u.name, u.score
FROM Friends FR
JOIN Users U ON U.facebookID = FR.facebookFriendID
WHERE FR.userID = 'A' ) t
SQL Fiddle Demo
Also, by the way your using ROW_NUMBER, it really will be a Row Number vs a RANK. If you want Rankings (with potential ties), replace ROW_NUMBER with RANK.

SELECT certain fields based on certain WHERE conditions

I am writing an advanced MySQL query that searches a database and retrieves user information. What I am wondering is can I select certain fields if WHERE condition 1 is met and select other fields if WHERE condition 2 is met?
Database: users
------------------------
| user_id | first_name |
------------------------
| 1 | John |
------------------------
| 2 | Chris |
------------------------
| 3 | Sam |
------------------------
| 4 | Megan |
------------------------
Database: friendship
--------------------------------------
| user_id_one | user_id_two | status |
--------------------------------------
| 2 | 4 | 0 |
--------------------------------------
| 4 | 1 | 1 |
--------------------------------------
Status 0 = Unconfirmed
Status 1 = Confirmed
OK, as you can see John & Megan are confirmed friends while Chris & Megan are friends but the relationship is unconfirmed.
The query I am trying to write is as follow: Megan(4) searches for new friends I want all of the users except for the ones she is a confirmed friend with to be returned. So, the results should return 2,3. But since a relationship with user_id 2 exists but is not confirmed, I want to also return the status since an entry in the friendship table does exist between the two. If a user exist but there is no connection in the relationship table it still returns that users information but returns status as a NULL or doesn't return status at all since it doesn't exist in that table.
I hope this makes since. Ask questions if you need to.
Why not use a left join or an if-not-exists?
SELECT users.*
FROM (users LEFT JOIN friendships
ON status=1 AND (user_id_one=user_id OR user_id_two=user_id) )
WHERE
status IS NULL
or
SELECT users.*
FROM users
WHERE
NOT EXISTS (SELECT *
FROM friendships
WHERE status=1
AND (user_id_one=user_id
OR user_id_two=user_id))
You can create to separate queries and then UNION the result tables. In each query, add a field that always has the same value.
So something like this should work:
(SELECT id, 'Not Friends' As Status FROM t1 WHERE condition1)
UNION
(SELECT id, 'Unconfirmed' As Status FROM t1 WHERE condition2)
Just make sure the same number and name of fields exists in both queries.

SQL: get Nth item in each group

I have a user table like this
user_id | community_id | registration_date
--------------------------------------------
1 | 1 | 2008-01-01
2 | 1 | 2008-05-01
3 | 2 | 2008-01-28
4 | 2 | 2008-07-22
5 | 3 | 2008-01-11
For each community, I would like to get the time that the 3rd user registered. I can easily do this for a single community using MySql's 'limit' SQL extension. For example, for community with ID=2
select registration_date
from user
order by registration_date
where community_id = 2
limit 2, 1
Alternatively, I can get the date that the first user registered for all communities via:
select community_id, min(registration_date)
from user
group by 1
But I can't figure out how to get the registration date of the 3rd user for all communities in a single SQL statement.
Cheers,
Don
With an inner select:
select
registration_date, community_id
from
user outer
where
user_id IN (
select
user_id
from
user inner
where
inner.community_id = outer.community_id
order by
registration_date
limit 2,1
)
order by registration_date
Selects the set of users where each user is the 3rd user in their community as returned by the limit clause in the inner select.
Is this what you mean?
SELECT registration_date
FROM user
ORDER BY registration_date
LIMIT n
Where n is the user you are concerned about.