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

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

Related

Improve query performance for a large join

I am trying to get a list of users who did a pull request on any repos with a specified language.
SELECT distinct(actor_id) as id FROM pull_requests
JOIN (SELECT id FROM repos WHERE language = 'javascript') as res
ON pull_requests.repo_id = res.id
I've been trying to improve the performance of this query. Currently it takes 2sec+ to run.
First thing -- try a semi-join:
SELECT distinct actor_id as id
FROM pull_requests p
where exists (
select null
from repos r
where p.repo_id = r.id and r.language = 'javascript'
)
Secondly -- verify your distinct is necessary based on this change. It probably is in this case, but semi-joins can often times eliminate the need for distinct where the it's used as a crutch for a 1::many returning multiple rows -- the exists will not multiply results based on multiple matches in the repos table.
Try this:
SELECT distinct(A.actor_id) as id FROM pull_requests AS A
INNER JOIN repos AS B ON A.repo_id = B.id AND B.language = 'javascript'
You may need to index on either repo_id and/or id field
Try using IN
SELECT distinct(actor_id) as id
FROM pull_requests
WHERE pull_requests.repo_id IN (SELECT id FROM repos WHERE language = 'javascript')

Counting Active Connections

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

Best way to construct this query? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Retrieving the last record in each group
I have two tables set up similar to this (simplified for the quest):
actions-
id - user_id - action - time
users -
id - name
I want to output the latest action for each user. I have no idea how to go about it.
I'm not great with SQL, but from what I've looked up, it should look something like the following. not sure though.
SELECT `users`.`name`, *
FROM users, actions
JOIN < not sure what to put here >
ORDER BY `actions`.`time` DESC
< only one per user_id >
Any help would be appreciated.
SELECT * FROM users JOIN actions ON actions.id=(SELECT id FROM actions WHERE user_id=users.id ORDER BY time DESC LIMIT 1);
you need to do a groupwise max - please refer to examples here http://jan.kneschke.de/projects/mysql/groupwise-max/
here's an example i did for somone else which is similar to your requirements:
http://pastie.org/925108
select
u.user_id,
u.username,
latest.comment_id
from
users u
left outer join
(
select
max(comment_id) as comment_id,
user_id
from
user_comment
group by
user_id
) latest on u.user_id = latest.user_id;
select u.name, a.action, a.time
from user u, action a
where u.id = a.user_id
and a.time in (select max(time) from action where user_id = u.user_id group by user_id )
note untested - but this should be the pattern
DECLARE #Table (ID Int, User_ID, Time DateTime)
-- This gets the latest entry for each user
INSERT INTO #Table (ID, User_ID, Time)
SELECT ID, User_ID, MAX(TIME)
FROM actions z
INNER JOIN users x on x.ID = z.ID
GROUP BY z. userID
-- Join to get resulting action
SELECT z.user_ID, z.Action
FROM actions z
INNER JOIN #Table x on x.ID = z.ID
This is the greatest-n-per-group problem that comes up frequently on Stack Overflow. Follow the tag for dozens of other posts on this problem.
Here's how to do it in MySQL given your schema with no subqueries and no GROUP BY:
SELECT u.*, a1.*
FROM users u JOIN actions a1 ON (u.id = a1.user_id)
LEFT OUTER JOIN actions a2 ON (u.id = a2.user_id AND a1.time < a2.time)
WHERE a2.id IS NULL;
In other words, show the user with her action such that if we search for another action with the same user and a later time, we find none.
It seems to me that the following will be works
WITH GetMaxTimePerUser (user_id, time) (
SELECT user_id, MAX(time)
FROM actions
GROUP BY user_id
)
SELECT u.name, a.action, amax.time
FROM actions AS a
INNER JOIN users AS u ON u.id=a.user_id
INNER JOIN GetMaxTimePerUser AS u_maxtime ON u_maxtime.user_id=u.id
WHERE a.time=u_maxtime.time
Usage of temporary named result set (common table expression or CTE) without subqueries and OUTER JOIN is the way best opened for query optimization. (CTE is something like a VIEW but existing only virtual or inline)

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;

Selecting records in SQL based on another table's contents

I'm a bit new to SQL and have trouble constructing a select statement. I have two tables:
Table users
int id
varchar name
Table properties
int userID
int property
and I want all user records which have a certain property. Is there a way to get them in one SQL call or do I need to first get all userIDs from the properties table and then select each user individually?
Use a JOIN:
SELECT U.id, U.name, P.property FROM users U
INNER JOIN properties P ON P.userID = U.id
WHERE property = 3
If there's only one property row per user you want to select on, I think this is what you want:
select
users.*
from
users,
properties
where
users.id = properties.userID
and properties.property = (whatnot);
If you have multiple property rows matching "whatnot" and you only want one, depending your database system, you either want a left join or a distinct clause.
Check out the JOIN command. You could write a query like the following:
SELECT
name
FROM
users u
INNER JOIN properties p
ON u.id = p.userID
WHERE
p.property = <some value>
You're looking to JOIN tables.
Assuming the id and userID columns have the same meaning, it's like this:
select u.name
from users u inner join properties p
on u.id = p.userID
where p.property = :ValueToFind
SELECT [Name] FROM Users u
JOIN Properties p on p.UserID=u.ID
WHERE p.Property=1
Obviously it depends what flavour of RDBMS and TSQL you are using.