How to retrieve the last row (by time) from each user - mysql

I have a basic table which hold record of which user viewed which list.
Each time a list is viewed, a record is stored into the "views" table, storing user_ID and list_ID, along with the time at which it is stored.
I want to know for each user when the last viewed a list, and which list it was.
I'm kinda stuck here. It gives me al the latest times, by order, but for some users I get multiple records.
How to sort this out?
http://sqlfiddle.com/#!2/39f41/4

sqlFiddle
SELECT user_ID, list_ID, max(times) as times
FROM views
GROUP BY user_ID, list_ID;
or if you want the view_id returned as well and assuming that larger view_id will always be at a later time than a smaller view_id you can use sqlFiddle
SELECT max(view_ID) as view_ID,user_ID, list_ID, max(times) as times
FROM views
GROUP BY user_ID, list_ID;

Related

MySQL COUNT(Value) between certain dates returning wrong value for count

I have been searching for an answer to the following but with no success as yet. I am trying to count the number of times a level is achieved by a user within a particular department.
After several attempts I've managed to get results from the query below, however the results are not between the timestamp values required, rather they show the total count for LEVEL. Timestamp is the name of the column in the table, could that be an issue?
SELECT COUNT(LEVEL) AS number, LEVEL, user, department FROM table
WHERE LEVEL ='3' AND TIMESTAMP>= '1500098552' AND TIMESTAMP<= '1568000152'
GROUP BY user ORDER BY number DESC
I have tried using various methods for the WHERE clause including BETWEEN but to no avail.
Any advice would be appreciated, thanks.
Try this one
SELECT COUNT(LEVEL) AS number, LEVEL, user, department FROM table
WHERE LEVEL ='3' AND TIMESTAMP>= 1500098552 AND TIMESTAMP<= 1568000152
GROUP BY user,department,LEVEL ORDER BY number DESC

SQL Query to return most recent row per user

Here is my table structure
So I have these columns in my table:
UserId Location Lastactivity
Let's say that there are 4 results with a UserId of 1 and each location is different. Let's say
index.php, chat.php, test.php, test1.php
.Then there are also timestamps.
Let's also add one more with a UserId of 4 location of chat.php and time of whatever.
Time is in the timestamp format.
I want to get it so that my sql query shows one result from each userid but only the latest one. So in 2 it would show the row which was added to the table most recently. Also I don't want it to show any results that have a lastactivity that was 15 or more minutes ago.
For the example I would just be displaying two rows returned.
Does anyone know what I should do?
I have tried:
SELECT * FROM session WHERE location='chat.php' GROUP BY userid
That returns two results but I believe if there are multiple results for the userid it returns a random one, it also returns results that have a lastactivity of more than 15 minutes.
I am using mysql
------MORE INFO-------
I want to query the database for all the rows where location='chat.php'. I only want one row per userid which is determined by whichever is the most recent submission. Then I also don't want any that are older than 15 minutes. Finally I want to count the number of rows returned and put them into a variable called testVar
Help would be appreciated.
Essentially what you are looking for boils down to you wanting the username and location with the most recent time stamp. So, you want to ignore all the records whose last activity is not the greatest.
Select sum(1) as testVar
From session s
Where location='chat.php'
and datediff(minute, s.lastactivity, getdate()) < 15
and not exists (Select *
From session s2
Where s.userid = s2.userid
and s2.lastactivity > s.lastactivity);
For each record, this query checks to see if there is another record for the same user where the time stamp is more recent. If there is, we want to ignore that record. We only want the rows where a record with more recent activity doesn't exist. It is a little strange to think about it this way, but the logic is equivalent.
By default this query will only grab one row per user, so a group by is not necessary. (This does get a little hairy if the time stamps are exactly the same for two records. In this case, no records will be pulled back)

How to count the number of individual users in a table per day?

I have a log table that lists various actions of a system, including user logins. I want to find out how many unique users logged in during each day.
I tried this here:
SELECT date, count(username)
FROM universal_log
WHERE (plugin,action)
IN (('system','login'))
GROUP BY date
ORDER BY date
which however gives me the amount of people who logged in, counting also all multiple logins by each user. I figured this is because I did not group by username. However if I do this here:
SELECT date, count(username)
FROM universal_log
WHERE (plugin,action)
IN (('system','login'))
GROUP BY date, username
ORDER BY date
I get a table with several entries per date instead of one, with the count how often each user logged in during that day.
How can I get a count +1 for each user when he logged in per day, no matter how often he logged in on that day?
Using a COUNT(DISTINCT username) should solve the duplications for you when applied to your first query. You were correct to GROUP BY date only, but just need to deduplicate the username values.
SELECT
date,
count(DISTINCT username)
FROM universal_log
WHERE (plugin,action)
IN (('system','login'))
GROUP BY date
ORDER BY date
When you added username to the GROUP BY in your second attempt, that had the effect of applying the COUNT() per date, per username, which is semantically different from what you want. For each column added to the GROUP BY, your aggregate will end up either producing more rows (applied over a wider data set) or in some cases the same rows (if the values were all distinct to begin with).

Count record views for a time period

I have a DB with a lot of records (of articles) and currently I keep track of how many times each record has been viewed by counting the views so I can sort on somehting like "see the top 5 most viewed articles"
This is done with a column of integers, and whenever the record is retrieved, the integer count increases by 1.
This works fine but since the counting system is very simple, I can only see views of "all time".
I would like to have something like "see the top 5 most viewed articles this week".
The only way I can think of is to have a separate table which makes a record with the article Id and Date whenever an article is viewed, and then make a SELECT statement for a limited time period.
This could easily work, but at the same time the table would be very large in no time.
Is there any better way of acomplishing the same thing? I've seen the sorting criteria on many websites, but I dont know how this is achieved.
Any thoughts or comments?
Thanks in advance :)
Instead of a row for each view of each article, you could have a row per day. When an article is viewed, you would do:
INSERT INTO article_views (article_id, date, views)
VALUES (#article, CURRENT_DATE(), 1)
ON DUPLICATE KEY UPDATE views = views + 1;
Then to get the top 5 articles viewed in the past week:
SELECT article_id, SUM(views) total_views
FROM article_views
WHERE date > NOW() - INTERVAL 7 day
GROUP BY article_id
ORDER BY total_views DESC
LIMIT 5
To keep the table from growing too large, you can delete old records periodically.

Count rows where user has multiple rows

I have a table of transactions that records the person that made the purchase. I want the number of people that have had more than one transaction. The part I became stuck at is how do I specify that Member must match at least twice (e.g. two or more transactions)?
I figured it'd be something along the lines of
SELECT COUNT(*) FROM `table` WHERE COUNT(`Member`)>2
but I realize that isn't a proper usage of the second count.
To further clarify: I want the result to be a single row that contains the number of users that this condition matches. So I don't want it to return how many times it matches per user or anything like that.
you need to use GROUP BY and HAVING.
SELECT COUNT(*) totalMember
FROM
(
SELECT Member
FROM `table`
GROUP BY Member
HAVING COUNT(Member) > 2
) a