MySQl - update field by counting data in other table - mysql

There are two tables. One is users info "users", one is comments info "comments".
I need to create new field "comments" in users table, that contains number of comments of that user. Table "comments" has "user" field with user's id of that comment.
What is optimal way to count number of comments by every user so far?
With php you should write script that selects every user and than count number of his comments and then update "comments" field. It is not hard for me, but boring.
Is it possible to do it without php, only in MySQL?

UPDATE TABLE users SET CommentCount = (SELECT COUNT(*) FROM comments WHERE AuthorUserId = users.id)

Why do you want to store it there anyway?
Why not just show it combined query?
select users.name, count(comments.id) as comment_count
from users
join comments on users.id=comments.user_id
group by users.id
If you want to do it your way then include
update users set comment=comment+1 where id=$user_id
into the script where you store the comment.
And
update users set comment=comment-1 where id=$user_id
into the place where user can delete his comment. Otherwise your data might be out of sync when user adds new commnts and you haven't run the script yet.

Yes, it is possible.
This is called table joining.
You don't add another field to the users table, but to the resulting table.
SELECT users.*, count(comments.id) as num_comments
FROM users,comments
WHERE comments.cid=users.id
GROUP BY users.id
Such a query is what relational databases were invented for. Do not revert it to the plain text file state. There is many reasons to make it that way.
http://en.wikipedia.org/wiki/Database_normalization <-- good text to read

Related

How to show username if i have 2 tables, user and review

i am creating a restaurant review website. in my review table i have a foreign key called user_id and idk how to use it to display the username which is in the user table
my user table
my review table
so my question is how do i display the username from this? what mysql statement do i have to write. I am lost on what to do
Assuming you want to try and get the review text along with the user name from the corresponding user you can use a join to combine the info for example:
SELECT u.username, r.review_text
FROM reviews r
LEFT JOIN users u
ON (u.user_id = r.user_id)
I assumed the users table is called users and reviews table is called reviews but update those as necessary each is "aliased" as u and r respectively and then tables are joined
If the relationship between the two tables is mapped out correctly you should be able to run a query to fetch the name of each user. Try to avoid any N+1 query though

mysql - Maintaining Subscription List of a Group in a Website

I'm creating a website where the users can join certain groups. Now I need to maintain the set of users in each group and/or the set of groups that each user has joined. Since MySql doesn't support arrays, I cannot maintain say, an array of users in a group(as a field in the "groups" table) or an array of groups in a user(as a field in the "users" table). So how can I achieve this?
My current solution is to maintain a table of group-subscriptions which has fields for the userID and groupID. So when I need either of these two lists I can do,
SELECT USERID FROM SUBSCRIPTIONS WHERE GROUPID=3
or
SELECT GROUPID FROM SUBSCRIPTIONS WHERE USERID=4
This will get me the desired lists. Is this the most efficient/standard way to do this or is there a better way?
You wrote all right.
Normally there are 3 types of relations between records in relative databases:
One - one (e.g. user and profile linked via user.profile_id = profile.id)
One - many (user and messages linked via message.user_id = user.id)
Many - many
Your case is the last and it always works via a 3rd table.
For your case it can be users_subscriptions (user_id, subscription_id)
Example query to select all users with their subscriptions:
SELECT u.name, GROUP_CONCAT(s.name) as `subscriptions`
FROM users u
JOIN users_subscriptions us ON us.user_id = u.id
JOIN subscriptions s ON us.subscription_id = s.id
GROUP BY u.id
If I understand your question correctly, that is the standard way.
You've created a "pivot table" that sits between the user table and the groups table and it stores the relationships between the two. This is the way that many-to-many relationships are stored in relational databases. As you correctly stated, you can retrieve all members of a group or all groups for a member that way.

How to avoid table for each user

I have a rather special use case in front of me. There is to be an excel file with around a thousand entries (rows), each row represents something that the USER should pass judgment on.
Now, the entries are the same for everyone. The data that should be collected is
a) how many users like any given entry
b) what entries does any given user like
Since part of the app is already running and we have user accounts,
I thought of creating a table for each user (!) containing said excel information, adding a row for collecting the votes. I would create those tables by iteratin through the user list and creating tables like "userid_excelentries".
I don't think that's elegant. I would prefer to store the excel information only once in a table and only save the users' votes in the table "user".
The app is meant to display a table created form the excel table (I have the grid already done) and a row next to it with checkboxes. How do I structure this ? Temporary tables ? How do I store the information what each user has selected in the "user" table, since I don't know how many selections will be made a-priori ?
I had this crazy idea of actually handling the xls object through javascript, serializing it into a hash and storing that hash into a field in each user's row...but I have no clue if this is sane :o
We're facing a user count of exactly 272 - this is why I considered doing the "one table for each user" approach.
You can use 3 tables in your DB
users table
-----------
id
name
...
entries table
-------------
id
name
...
user_entries table
------------------
user_id
entry_id
user_response
To get all entries a certain user (i.e. Tom) likes you can do
select e.name
from entries e
join user_entries ue on ue.entry_id = e.id
join users u on ue.user_id = u.id
where u.name = 'tom'
and ue.user_response = 'like'
And to get the count of likes for each entry you can do
select e.name, count(ue.user_id) as likes
from entries e
join user_entries ue on ue.entry_id = e.id
where ue.user_response = 'like'
group by e.id, e.name

How do I select a record from one table in a mySQL database, based on the existence of data in a second?

Please forgive my ignorance here. SQL is decidedly one of the biggest "gaps" in my education that I'm working on correcting, come October. Here's the scenario:
I have two tables in a DB that I need to access certain data from. One is users, and the other is conversation_log. The basic structure is outlined below:
users:
id (INT)
name (TXT)
conversation_log
userid (INT) // same value as id in users - actually the only field in this table I want to check
input (TXT)
response (TXT)
(note that I'm only listing the structure for the fields that are {or could be} relevant to the current challenge)
What I want to do is return a list of names from the users table that have at least one record in the conversation_log table. Currently, I'm doing this with two separate SQL statements, with the one that checks for records in conversation_log being called hundreds, if not thousands of times, once for each userid, just to see if records exist for that id.
Currently, the two SQL statements are as follows:
select id from users where 1; (gets the list of userid values for the next query)
select id from conversation_log where userid = $userId limit 1; (checks for existing records)
Right now I have 4,000+ users listed in the users table. I'm sure that you can imagine just how long this method takes. I know there's an easier, more efficient way to do this, but being self-taught, this is something that I have yet to learn. Any help would be greatly appreciated.
You have to do what is called a 'Join'. This, um, joins the rows of two tables together based on values they have in common.
See if this makes sense to you:
SELECT DISTINCT users.name
FROM users JOIN conversation_log ON users.id = converation_log.userid
Now JOIN by itself is an "inner join", which means that it will only return rows that both tables have in common. In other words, if a specific conversation_log.userid doesn't exist, it won't return any part of the row, user or conversation log, for that userid.
Also, +1 for having a clearly worded question : )
EDIT: I added a "DISTINCT", which means to filter out all of the duplicates. If a user appeared in more than one conversation_log row, and you didn't have DISTINCT, you would get the user's name more than once. This is because JOIN does a cartesian product, or does every possible combination of rows from each table that match your JOIN ON criteria.
Something like this:
SELECT *
FROM users
WHERE EXISTS (
SELECT *
FROM conversation_log
WHERE users.id = conversation_log.userid
)
In plain English: select every row from users, such that there is at least one row from conversation_log with the matching userid.
What you need to read is JOIN syntax.
SELECT count(*), users.name
FROM users left join conversion_log on users.id = conversation_log.userid
Group by users.name
You could add at the end if you wanted
HAVING count(*) > 0

Best method for storing data in mysql?

I have a pretty basic question on which is the preferred way of storing data in my database.
I have a table called "users" with each user getting a username and user_id. Now, I want to make a table called "comments" for users to comment on news.
Is it better to have a column in comments called "username" and storing the logged in user's name, or have a column called "user_id". If I use user_id I would have to make my sql statement have another select statement. "(SELECT username FROM users WHERE users.id = comments.user_id) as username". It seems like performance would be better just storing the username.
I thought I read to avoid duplicate data in a database though.
Which is better?
Thanks
Typically, you use ID fields to link tables together. The reason being (in your situation) that you might allow the person to change their username, but you don't want to try and update all the places that is at...
Therefore, put the user_id in your comments table and pull the username out on a join, as you've shown.
If the user_id is the primary key then you should use user_id instead of username, if you want to use username instead of user_id then why do you have a user_id in the first place?
If there's the potential of creating a large enough database, store the user_id in the comments table. Less overhead. Also consider that usernames my be modified easier this way.
Data should be stored in (at least) third normalized form, so you should use the user_id as the primary key in the users table, and as a foreign key in the comments table and use this to get the details:
SELECT comments.*, users.username
FROM comments, users
WHERE users.user_id = comments.user_id;
If you are getting the comments based on an article, you could do this like this:
SELECT comments.*, users.username
FROM comments, users
WHERE users.user_id = comments.user_id
AND comments.article_id = '$current_article_id';
Storing the userid (integer) will mean faster JOINs later. Unless you plan on having people dig through the database by hand, there's really no reason to use the username
I'm pretty sure storing the user id in the comments table is sufficient. If you're returning rows from the comments table, just use the JOIN statement.
Cheers
Which is going to be a unique identifier? The user_id, I'd bet, or you can't have two "John Smith"s in your system.
And if volume is much of a concern, text matching the username field is going to be more expensive than linking to the users table in your query in the long term.
Numeric values are cheaper to join and index than an alphanumeric id. Use a number to uniquely identify a row. Another benefit is that the PK doesn't need to change if they need to change the user id. The last benefit is that this is the design of most modern web frameworks such as django and rails.