PHP MySQL calculate how many rows have the same data - php

Ok, well I know I can just say WHERE example='vrvrv' but that's not the case. Ok I have a rating system and whenever a page is rated the page id and the date it was rated is sent to a table in my database. Now on the homepage I want to determine top rated that day, I can easily compare dates but I'm not quite sure how to count how many rows have the same value in the project_id column. It would be amazing if someone could help me out, thanks!

You can use GROUP and COUNT to get duplicates:
SELECT count(`project_id`) AS `duplicates` FROM `table` GROUP BY `project_id` HAVING `duplicates` > 1

Related

Select from database with count and count based conditions?

I have a table with data relating to a user, and two important columns:
refer_count, which is updated when a new entry is made in the table with the referred_by column set to that users user_id, and referred_by which is the user_id of the of the user that referred them.
I want to select the users from the table that have the highest number of referrals after a certain date.
For example:
If there are 3 users, one of which referred the other 2 (lets say users 2 and 3), however user 2 was referred on the 2/12/14, whereas user 3 was referred on the 3/1/15.
If the cutoff is 1/12/14, then user 1 is returned with refer_count set to 2, but if the cutoff is after 2/12/14, then user 1 is returned with refer_count set to 1.
I've been thinking of how to do this, but I can't think of a way that would work. Is there a way?
This is via MySQL.
EDIT: I think I may need to provide for information.
The date registered (register_date) is used as the refer date. I need the refer_count to be updated with the number of users referred after the cutoff, however I need to get the actual user. This is for a 'top referrers' table. I can't figure out why I'm having so much trouble thinking of a way to do this.
SELECT user_id FROM usertable WHERE (referal_date BETWEEN '2014-12-2' AND CURDATE())ORDER BY refer_count DESC;
That's the rough idea.
You should look into normalizing your tables if you're keeping that all in the same table, though. It'd be better to keep referals in a seperate table.
Get the row with the maximum in refer_count with a Date condition for your referal_date such that it's after the certainDate:
SELECT user_id FROM table WHERE refer_count = (SELECT MAX(refer_count) FROM table) AND referal_date>certainDate;
Note that WHERE is before SELECT so it will not get the highest count first, but will filter with the date condition then get the highest count.
Edit: Updated query based on edited question.

Limiting row count to a specific number when inserting

I'm thinking of implement a view history for my wordpress blog, where users can view their previously viewed articles as a list in their account page.
I would like to limit this to 24 unique page history per user at any point of time, meaning, if the number of articles exceeds 24, the oldest article row would be deleted, and the new article added to the table.
I'm using PHP and MySQL.
Here's my current thoughts on implementation:
Create a table with user_id and post_id columns
When user views an article, insert new row into the table
Select the rows with the current user_id, and if number of rows is more than 24,
Delete the oldest row
I'm not sure if this is the best method, since it's 3 additional database queries per user page view which is pretty heavy.
Is there a better way to do this?
The ideea is good. Improve it by updating the oldest row instead of deleting it and then adding a new one. ;)
Also make a single read query and a single write query.
make a query that is like this one
SELECT (SELECT COUNT(*) FROM recentArticles WHERE userID = 23)
AS NoOfArticles, articleID, timestamp
FROM recentArticles
WHERE userID = 23
ORDER BY timestamp ASC
LIMIT 1;
If NoOfArticles < 24 then execute an insert query, else execute an update query to articleID
You could always implement this using cookies to key on which pages have been visited and keeping a running list on the users PC. This will reduce the traffic to the site, put the processing scripts on the user-side, and could be easier to implement.
That being said, I agree with the other answer about updating the oldest entry if the table is full. This eliminates the need to delete and add a row. Key off a time-date stamp to sort the entries when you're displaying them and to figure out which page was the oldest (and needs to be updated if >= 24 pages.
You can merge two queries in one. In this way, You will save execution time of your script. So, basically, DELETE row if the post count is more than 24. You can modify this query according to your exact need. But yes, you can think on this way.
DELETE FROM `table_name`
WHERE id=(SELECT (CASE WHEN COUNT(id)>24 then id END)
AS last_id
FROM `table_name`
WHERE user_id='XX'
ORDER BY id DESC LIMIT 1);

Get the sum of a column value for all rows with same value in different column

I need to know how to handle a pretty complex situation.
I have a system that allows users to vote up or down on comments that others make. I want to create a report of those with the most up votes based on all of their comments. The upvotes were not tracked in the users table, only in the comments table so it needs to go through the comments table and get the value in the vote column and output the sum of all of the vote column values for each userid. It then needs to order these and output the top 10.
Thanks in advance for help
If you post your users and comments table structure I could make a query. But it would be something like this:
SELECT SUM(votes) total, user_id FROM comments GROUP BY user_id ORDER BY total LIMIT 10

Alternative solution for PHP/SQL max array size problem

I have a table bundled among 100 databases in MYSQL (i.e. 1st x rows of the table in database_1, 2nd x rows of the table in database_2, ... , last x rows of the table in database_100)
Each table has a row whenever a user visits a friend for a game.
The columns are iuin, logtime, beuin.
iuin is the user id of the visitor.
beuin is the user id of the friend who was visited.
logtime is when the visit was made.
I would like to find the # of distinct friends who were visited during a week.
There is roughly 300k distinct users who are visited per day.
However, when I extended my code to calculate for a week, I ran out of memory.
My code basically does an SQL query using SELECT DISTINCT beuin for a selected week for the table in each database. I store all the beuin in an array if it's not already stored (so I count distinct friends who were visited), and return the size of the array at the end.
FYI, I can't edit the database around such as joining all the tables in different databases into one table.
Is there any alternative ways i can do this?
Thanks
It's hard to say anything about your without the one. But I think you can solve this problem using mysql. My quick solution:
Create table - CREATE table if not exist users_ids(user_id INT NOT NULL DEAULT 0 PRIMARY KEY(UNIQUE)); in the first db
Truncate users_ids
Run 100 queries like INSERT IGNORE INTO db1.users_ids select distinct user_id from db1.table1;
Select count(*) from users_ids;

MySQL: Pulling the current user's vote on a query of links

So I have this query that pulls from my links and votes table and I need one last column of data. My votes table consists of every user's vote, a user can only vote once per link and their vote value is either -1, 0 or 1. There is a user_id foreign key in the votes table and I want to somehow gather the current user's vote. I feel the complexity of the current query might require a second query but I really want to avoid that if possible. I simply need to know what the current logged in user's vote was. A link will never have more than one vote value because a user can only vote on a link once.
A few notes
All links start automatically with at least one vote entry by the current user
A user that votes on a link then deselects that vote will keep that vote entry with a 0 delta
SQL:
SELECT links.*, (SUM(votes.karma_delta)) AS karma
FROM links, votes
WHERE links.id = votes.link_id
GROUP BY votes.link_id
ORDER BY (SUM(votes.karma_delta) - 1) / POW((TIMESTAMPDIFF(HOUR, links.created, NOW()) + 2), 1.5) DESC
LIMIT 0, 100
While optimization is great, right now I just want to get the selected links karma_delta by a specified user.
I'm really not sure of what you're asking, but it sounds like you want to keep the information you're already returning and simply augment it with the sum of votes pertaining to the current user for each link.
If that's the case, then something like this should do it:
SELECT links.*,
SUM(votes.karma_delta) AS karma,
SUM(
IF(votes.user_id = current_user_id,
votes.karma_delta,
0)
) AS user_vote
FROM links, votes
WHERE links.id = votes.link_id
GROUP BY votes.link_id
ORDER BY (SUM(votes.karma_delta) - 1) /
POW(
TIMESTAMPDIFF(HOUR, links.created, NOW()) + 2,
1.5
) DESC
LIMIT 0, 100
Here is one way you can make this faster: if you need to show the scores for each of the links frequently, and you vote on the links not very frequently, I'd denormalize the data structure in the following way:
Create a column on the link table called "current score"
Whenever you make a modification to the votes table, also update the current score
If you ever worry about the two getting out of sync, run a daemon that overrides the values of the current score with the "aggregation of all votes".
Then, showing the score of each of the links is mega-fast; of course, the cost you're paying here is at the vote time (you're doing two inserts/updates instead of one), as well as some extra complexity.

Categories