Mysql COUNT VS num rows performance - mysql

I want to select the amount of forum posts compared to a list of users. So it will look like this:
USERID --- FORUMPOSTS
3647 - 2
7467 - 14
2673 - 39
3224 - 5
... and so on
Now I'm asking if it would be faster to count the forum post via COUNT(*) or looping through the userlist before and creating a new query for each user to count his/her forum posts via mysql_num_rows.

You can let SQL do the grouping and counting
select userid, count(*) as forumposts
from your_table
group by userid

Now I'm asking if it would be faster to count the forum post via COUNT(*) or looping through the userlist before and creating a new query for each user to count his/her forum posts via mysql_num_rows.
It'll be faster to do the former, "count the forum post via COUNT(*)". You can group the results as follows:
SELECT userid, COUNT(*) FROM my_table GROUP BY userid
It'll be even faster still if your table has an index on the userid column.

Related

Laravel Mysql statement like fcm topic condition

I'm trying to make my own topics system similar to fcm on mysql.The table is simply this:
user_id topic_name
In fcm for example:
'topic1' in topics && 'topic2' in topics or ('topic3' in topics)
means select the user, which is subscribed to topic1 and topic2 or is subscribed to topic3.
In mysql I have no idea how to do this,basically it's based on all equavelnt user_ids but on different conditions on topic_name but using whereIn and whereNotIn and stuff it's not possible I'm really confused.
I suspect that you want aggregation and a having clause:
select user_id
from mytable
where topic_name in ('topic1', 'topic2', 'topic3')
group by user_id
having count(*) = 3
This brings users that have the three topics listed in the where clause.

Query for average response time in mysql

I have a table with columns:
id , conversation_id , session_id , user_id , message , created_at
every time a user starts a conversation with an employee, a new session starts (different session number).all messages between every employees and users are stored in this table. the created_at column is a timestamp. I need to filter out sessions by employee number, and calculate the average response time between the first message a user sends and the first message sent back by a specific employee, for every session disregarding outlying data where either a customer or employee did not reply ( only one user in the session)
i know this is complicated but please help!
in this example in the user_id column, 4 is the employee ( keep in mind there are other employees). everytime a new conversation starts the session_id changes. i have to go through each session for a specific employee, take the timestamp of the first message sent by the customer as well as the employee, take the difference, sum all the differences and then take an average, while making sure that the session actually contains two users ( filtering outlying data).
So far, ive come up with this:
SELECT * FROM messages
WHERE session_id IN (
SELECT session_id FROM messages
WHERE user_id =4 )
GROUP BY session_id, user_id
to get the first message from each customer and employee (gives something like this)
so from this specific example, i would omit line 41040 as it only as the session contains only 1 person (column 3, id 1028) and is considered outlying data
I'm actually appalled by some of the comments... StackOverflow is meant to be a community for helping others. Why bother even taking up comment space if you're gonna complain about my ponctuation or give a vague, useless answer?
Anyways, i figured it out.
Basically, i joined the same table multiple times but only queried the necessary data. In the first join, I queried the messages table with the employee messages and grouped them by session number. In the second join, i did the same procedure but only extracted the messages from the user. By joining them on the session id, it automatically omits any sessions where either a user or employee is not present. By default, the groupby returns the first set of data from the group ( in this situation i didn't have to manipulate the groupby because I was actually looking for the first message in the session), I then took the average of the difference between the message timestamp for the user and employee.In this specific situation, the number 4 is the employee number. Here is what the query looks like Also, the HAVING AVG_RESP > 0 was necessary in this situation to remove outlying data when tests are performed :
SELECT AVG(AVG_RESP)
FROM(
SELECT TIME_TO_SEC(TIMEDIFF(t.created_at, u.created_at )) AS AVG_RESP
FROM (
SELECT * FROM messages
WHERE session_id IN (
SELECT session_id FROM messages
WHERE user_id = 4) AND user_id = 4
GROUP BY session_id
) AS t
JOIN(
SELECT * FROM messages
WHERE session_id IN (
SELECT session_id FROM messages
WHERE user_id = 4) AND user_id != 4
GROUP BY session_id
) as u
ON t.session_id = u.session_id
GROUP BY t.session_id
HAVING AVG_RESP > 0
) as ar
Hopefully this helps someone in the future, unlike the people who leave ridiculous, useless comments.

Find the one-time users in a system- sql table

I have a table with 6 columns- Date, time, action, user_id, channel, and time_and_date.
Action refers to open or close, when a user starts or end watching a tv channel.
My tasks are as following
to get an overview of the data:
- find the one-time users (who used the service only once or in only one day and
never came back) for each channel, each genre, each community
Anoother table provides the user_id, genre(news, sport....)
How can I find the one time users for those requirements?
You can try something like
SELECT FROM first_table LEFT JOIN users ON first_table.user_id=users.id GROUP BY users.id HAVING COUNT(users.id)=1
You can join your genre table after for selecting over genre channels...
To get the one-time users:
select user_id ,min(channel) as channel, min(genre) as genre, min(community) as community
from action_table
group by user_id
having min(date) = max(date);
Note the having clause. This guarantees that a users has only one date (but not necessarily one record).
This returns one value for each of the three dimensions -- for a one-time user they are the same. For someone who visits multiple times in one day, it chooses one value.
Sounds something like this:
select user_id, count(*)
from action_table
where action = 'open'
group by user_id
having count(*) = 1
order by user_id

Mysql form new optimize query

I have Four Tables in database,
users, count, coupon, account
Need number of users from following conditions:
Select All Users from users table then
Select from count where users are not in the list of last 14 days then
Select users which are not in the list, to check that there are in coupon table. If they are not in coupon table then take those users id then
Select account table and check that these users have any count or insertion in the account table. If yes then set all those users in an array or print it out as a result.
Please anybody help me in forming good query?
Thanks!
If I'm right take users
who aren't in the count table for the last 14 days
and
who aren't in the coupon table.
and
who are in the account table
Seems like a weird sql but here is an example:
SELECT
*
FROM
user
WHERE user_id NOT IN
(
SELECT
user_id
FROM
`count`
WHERE
DATE_SUB(CURDATE(),INTERVAL 14 DAY) <= date_column
)
AND user_id NOT IN
(
SELECT
user_id
FROM
coupon
)
AND user_id IN
(
SELECT
user_id
FROM
account
)
If this isn't right, your explanation of what you want is wrong and should be clarified .
Everything could be wrong with this sql, because I don't know your columns (user id? date?) .But I think you can change the sql to your liking.

Finding all polls that a specific user hasn't voted on yet

I have a website that displays poll after poll to a register user, and stores his vote in a table.
A simple structure of the database would be as follows (there are much more fields, but they don't contribute much to the question, so I removed them):
Polls(pollId)
Votes(pollId, userId, vote)
Now I want to run a MySql query to select all polls within the 'Polls' table, except for the polls that the current user had already voted on (which could be determined from the 'Votes' table)
Is it possible to make that using a MySql select statement alone, or will I have to select all polls first, and use some Php logic to filter out the ones already voted on by the user?
Thanks in advance!
SELECT *
FROM Pools
WHERE id NOT IN (
SELECT poolId
FROM Votes
WHERE userId = 142
)
Try something like this:
select p.pollid from polls p where p.pollid not in (select v.pollid from votes v where userId = {USERID})