Counting Active Connections - sql

I wanted to know what would be the best way to get a count of all the active connections per user in a DB setup like this. Only the first two groups should be used in the query. The Result Set is what I would like the output of the query to look like.
One thing to keep in mind is that it is possible that a Users record might have been deleted and not reflected in the Connections table. The result set should only count connections with other accounts that are still in the users table. I would also like to sort the results by the Count.

SELECT Users.UserId,count(*) Count
FROM ConnectionsTable
JOIN Users ON ( Users.UserId = Requestor OR Users.UserId = Requestee)
GROUP BY Users.UserId
ORDER BY count(*) DESC

SELECT source.UserId, COUNT(*) as [Count]
FROM
(
(
SELECT Requestor as UserID
FROM Connections
)
UNION ALL
(
SELECT Requestee as UserID
FROM Connections
)
) source
WHERE Exists (SELECT top 1 1 FROM Users us WHERE us.UserId = source.UserId)
GROUP BY source.UserId

Related

How to query top record group conditional on the counts and strings in a second table

I call on the SQL Gods of the internet!! O so desperately need your help with this query, my livelyhood depends on it. I've solved it in Alteryx in like 2 minutes but i need to write this query in SQL and I am relatively new to the language in terms of complex blending and syntax.
Your help would be so appreciated!! :) xoxox I cant begin to describe
Using SSMS I need to use 2 tables 'searches' and 'events' to query...
the TOP 2 [user]s with the highest count of unique search ids in Table 'searches'
Condition that the [user]s in the list have at least 1 eventid in 'events' where [event type] starts with "great"
Here is an example of what needs to happen
search event and end result example
So the only pieces i have so far are below but boy oh boy please don't Laugh :(
What i was trying to do is..
select a table of unique users with the searchcounts from the search table
inner join selected table from 1 on userid with a table described in 3
create table of unique user ids with counts of events with [type] starting with "great"
Filter the inner joined table for the top 2 search counts from step 1
SELECT userid, COUNT() as searchcount
FROM searches
GROUP BY userid
INNER JOIN (SELECT userid, COUNT() as eventcount
FROM events WHERE LEFT(type, 5) = "great" AND eventcount>0 Group by userid)
ON searches.userid=events.userId
Obviously, this doesn't work at all!!! I think my structure is off and my method of filtering for "great" is errored. Also i dont know how to add the "top 2" clause to the search table query without affecting the inner join. This code needs to be fairly efficient so if you have a better more computationally efficient idea...I love you long time
SELECT top(2) userid, COUNT() as searchcount FROM searches
where userid in (select userid from events where left(type, 5)='great')
GROUP BY userid
order by count() desc
hope above query will serve your purpose.
I think you need exists and windows function dense_rank as follows:
Select * from
(Select u.userid, dense_rank() over (partition by u.userid order by count(*) desc) as rn
From users u join searches s on u.userid = s.userid
Where exists
(select 1 from events e
Where e.userid = u.userid And LEFT(e.type, 5) = 'great')
Group by u.userid ) t Where rn <= 2

Two tables get values with common value or no value in other table

We have two tables.
Table 1 - Users: Contains the users
Table 2 - Restrictions: User that can only access certain room. If a user is not in this table they can access all the rooms.
Now I need a query where I pass the room and it returns the users that have access. For example, I pass RoomId = 70 and my expected result is 1, 3.
1 because it actually has access to only room 70 and 3 because since it's not in the restriction table it has access to all rooms.
The problem is with an inner join I lose number 3, and with left join I keep number 2. So I cannot figure out how to relate the tables. Is there any way to do it directly with joins?
You can try with UNION
SELECT usr.UserID FROM Users usr
JOIN Restrictions res ON usr.UserID = res.UserID
WHERE res.RoomID = #myParameter --we take the users permitted for given room
UNION
SELECT UserID
FROM Users
WHERE UserID NOT IN (
SELECT DISTINCT UserID
FROM Restriction
) --plus the users that have permission in all rooms
I think, this should work. You don't really need a join to solve the issue.
select
userid
from
users u
where
userid is not in (
select
userid
from
restrictions
where
userid = u.userid
and roomid = #roomId
)
I strongly advise you not to use not in with a subquery. It is just a dangerous habit. If the subquery returns any NULL values, then the outer query returns no rows.
So, I would recommend:
select userid
from users u
where exists (select 1
from restrictions r
where r.userid = u.userid and
r.roomid = 70
) or
not exists (select 1
from restrictions r
where r.userid = u.userid
);
I would also strongly advise you to change your data model. If someone has access to one room and that row is deleted from restrictions, then they will have access to all rooms. That seems dangerous. You should explicitly list all rooms useres have access to.

SQL - How to connect an UPDATE with a COUNT-function?

Hi I am quite new to SQL and I was trying to search here and on Tutorial sites but somehow can't get to a solution. My problem is actually simple.
I have 3 tables: tweets, users, bon_results.
In order to get my final .csv-data I need to add some values into the table 'users'. But those values I need to create via a function first. I need to do the following: Each tweet has a favorite_count. I need to SUM it up and GROUP BY user, like:
SELECT user, count(favorite_count) FROM tweets GROUP BY user
The Point is I need to write this into the table 'users' into a column 'favorite_count' and I seriously don't know how to connect these two steps. I tried it via the UPDATE-Statement like this:
UPDATE users
SET favorite_count=COUNT(favorite_count) FROM tweets
WHERE tweets.user=users.user
I know that the part after the "=" is bullshit but I don't know how to get the function COUNT into this.
Advice would be marvelous.
You should always tag the RDBMS you are using in the question.
You can use a Correlated query to the update in most of the databases:
update users u
set favorite_count = (
select count(favorite_count)
from tweets t
where t.user = u.user
);
If you don't want correlation, the other solutions are mostly vendor specific.
In SQL Server, you can use:
update u
set u.favorite_count = t.cnt
from users u join (
select
user,
count(favorite_count) as cnt
FROM tweets
GROUP BY user
) t on u.user = t.user;
In MySQL:
update users u join (
select
user,
count(favorite_count) as cnt
FROM tweets
GROUP BY user
) t on u.user = t.user
set u.favorite_count = t.cnt;
You were really close to the subquery version:
update users
set favorite_count = (
select count(favorite_count)
from tweets
where tweets.user=users.user
);
Inner join to a derived table (subquery) version :
update u
set favorite_count = t.favorite_count
from users u
inner join (
select user, count(favorite_count) as favorite_count
from tweets
group by user
) as t
on u.user = t.user
You can try this bro.
Update b
SET favorite_count=COunt(favorite_count)
FROM
tweets a
JOIN
Users b
ON a.Column1=b.Column1

INNER JOIN on change status

I have a table USERS with 3 columns
user_id, user_status and usr_update.
This last column says the date and time of the last change of status, I want to get the last change of status of a user.
I try this but doesn't work.
SELECT user_id, user_status, max(usr_update)
FROM USERS u1 INNER JOIN USERS u2
ON u1.user_id=u2.user_id
WHERE u1.user_id='123456' AND
u1.user_status<>u2.user_status
anyone can help?
#jarlh
it's ok but what if I have more consecutive record with the same state and I want to get the firs record with the new state?
for example
I want to get the record (id_15,blocked,17/10/2015)
SELECT user_id, user_status, usr_update
FROM USERS u1
WHERE NOT EXISTS (select 1 from users u2
where u1.user_id=u2.user_id
and u2.usr_update > u1.usr_update)
I.e. return a row if there are no later row for the same user.
If you only care about one user, then use order by and fetch only one row:
SELECT u.*
FROM (SELECT u.*
FROM users u
WHERE u.user_id = '123456'
ORDER BY u.usr_update DESC
) u
WHERE rownum = 1;
(Note: In Oracle 12+, you can use FETCH FIRST 1 ROW ONLY so the subquery is not needed.)
You can also do this using keep:
SELECT u.user_id, MAX(u.usr_update),
MAX(user_status) KEEP (DENSE_RANK FIRST OVER ORDER BY u.usr_update DESC) as last_user_status
FROM users u
WHERE u.user_id = '123456'
GROUP BY u.user_id;
This method will work without the WHERE clause. And, in my experience, KEEP performs quite well.

How to make a nested query?

Have a table users and there is a field invited_by_id showing user id of the person who invited this user. Need to make a MySQL query returning rows with all the fields from users plus a invites_count field showing how many people were invited by each user.
Something like this:
SELECT
User.*, Count.count
FROM
users AS User,
(
SELECT COUNT(*) AS count FROM users WHERE users.invited_by_id=User.id
) AS Count;
This one is not working so I need a working one.
SELECT u.*,
(
SELECT COUNT(*)
FROM users ui
WHERE ui.invited_by_id = u.id
) AS cnt
FROM users u
Ok, first of all, count is a reserved word in sql so you can't use it as a table alias (unless you quote it in some way but don't do that). Secondly, the real way to solve this problem is to introduce a GROUP BY clause in your subquery.
Try this:
SELECT user3.*, subquery.theCount FROM
users AS user3
INNER JOIN (
SELECT
user1.id, count(user2.id) AS theCount
FROM
users AS user1
LEFT OUTER JOIN
users AS user2 ON user2.invited_by_id=user1.id
GROUP BY user1.id
) AS subquery ON subquery.id=user3.id;
Here is a dirty little secret about MySQL: It lets you cheat with the GROUP BY statement and select columns that are not in the GROUP BY list and also not in aggregate functions. Other RMDMSes don't let you do this.
SELECT
user1.*, count(user2.id) AS theCount
FROM
users AS user1
LEFT OUTER JOIN
users AS user2 ON user2.invited_by_id=user1.id
GROUP BY user1.id;