Querying Last Entries group by DeviceId - mysql

I have the database table logs as the following:
alt text http://www.freeimagehosting.net/uploads/16e974703a.jpg
I would like to extract the last entry of device, pollDate, status. For eg.
deviceId, pollDate, status
1, 2010-95-06 10:53:28, 1
3, 2010-95-06 10:26:28, 1
I tried to run the following query but the distinct only selects the first records, not the latest
SELECT DISTINCT deviceId, pollDate, status
FROM logs
GROUP By deviceId
ORDER BY pollDate DESC
alt text http://www.freeimagehosting.net/uploads/5d181103f8.jpg
So, could you please help me to extract the latest entries from the table? Thanks.

If (deviceID, poll_date) is unique, you can do the following:
SELECT *
FROM (
SELECT deviceid, MAX(poll_date) AS md
FROM logs
GROUP BY
deviceid
) q
JOIN logs l
ON l.deviceid = q.deviceid
AND l.poll_date = q.md

Related

Mysql: Getting the 2nd earliest date for each group

Desired outcome:
I want to get the 2nd earliest date for each group.
Current:
I am getting the earliest date for each group
Query:
select * from
(select * from profile_match
where match_available_on is not null
order by profile_id asc, match_available_on asc)
as P1
group by P1.profile_id
Example: Link
From the example, I want to get:
1, '2015-05-20 03:50:11'
2, '2015-05-16 03:50:09'
And I hope that the query is not hard-coded with specific profile_id (1 or 2) as my actual data got lots of profile_id. Thanks guys!
This query will give you the results you want:
select t.profile_id, min(t.match_available_on )
from profile_match t
inner join (
select profile_id, min(match_available_on) match_available_on
from profile_match
group by profile_id
) q
on t.profile_id = q.profile_id
and t.match_available_on > q.match_available_on
group by t.profile_id;
By finding the minmatch_available_on, we can then range join against that, and choose the minimum joined value. This isn't going to be amazingly performant, but it will get the job done.
updated your demo here.
It will not return a row for a profile which has only one date available, as there is no 'second earliest'.

SQL User Transactions

I have a table with multiple users that keeps track of application login date and time.
I am looking for a way to pull the last date they log on to the app 1 entry per user?
Column1 = userid
Column2 = date
I have try multiple examples but none are working as bellow:
select *
from
(select *
from ACCTRANS
ORDER BY TIMESTAMP DESC) AS x
GROUP BY
USERID
SELECT UserId, MAX(TIMESTAMP)
FROM ACCTRANS
GROUP BY UserId

This slow MySQL Query needs improvement

This query works and provides me with the information I need, but it is very slow: it takes 18 seconds to agregate a database of only 4,000 records.
I'm bringing it here to see if anyone has any advice on how to improve it.
SELECT COUNT( status ) AS quantity, status
FROM log_table
WHERE time_stamp
IN (SELECT MAX( time_stamp ) FROM log_table GROUP BY userid )
GROUP BY status
Here's what it does/what it needs to do in plain text:
I have a table full of logs, each log contains a "userid", "status" (integer between 1-12) and "time_stamp" (a time stamp of when the log was created). There may be many entries for a particular userid, but with a different time stamp and status. I'm trying to get the most recent status (based on time_stamp) for each userid, then count the occurrences of each most-recent status among all the users.
My initial idea was to use a sub query with GROUP BY userid, that worked fast - but that always returned the first entry for each userid, not the most recent. If I could do GROUP BY userid using time_stamp DESC to Identify which row should be the representative for the group, that would be great. But of course ORDER BY inside of group does not work.
Any suggestions?
The first thing to try is to make this an explicit join:
SELECT COUNT(status) AS quantity, status
FROM log_table join
(select lg.userid, MAX( time_stamp ) as maxts
from log_table lg
GROUP BY userid
) lgu
on lgu.userid = lg.userid and lgu.maxts = lg.time_stamp
GROUP BY status;
Another approach is to use a different where clause. This will work best if you have an index on log_table(userid, time_stamp). This approach is doing the filtering by saying "there is no timestamp bigger than this one for a given user":
SELECT COUNT(status) AS quantity, status
FROM log_table
WHERE not exists (select 1
from log_table lg2
where lgu.userid = lg.userid and lg2.time_stamp > lg.time_stamp
)
GROUP BY status;

SQL QUERY:Repeated Occurrences of user-login after (and including) first occurrence

I need to find repeated occurrences of user login from loginhistory table after a given date. I tried following query, but it gives ZERO rows. loginhistory table has tow columns namely userkeyid, datecreated. Below is the query I am using:
Problem Statement:
*User logged in first time on or after 2013-10-26 and after logging in first time, all the repeated occurrences should be displayed till date. This should happen for all users who logged in first time on or after 2013-10-26 *
SELECT
FirstOccurenceHistory.firsttimeuserkeyid userkeyid,
firstOccurrenceDate,
DATE(fullhistory.dateCreated) repeatedOn
FROM (
SELECT DATE(dateCreated) firstOccurrenceDate,
COUNT(1) n,
userkeyid firsttimeuserkeyid
FROM
loginhistory
GROUP BY userkeyid
HAVING COUNT(userkeyid) = 1 and firstOccurrenceDate >= DATE('2013-10-26')
)
as FirstOccurenceHistory
INNER JOIN loginhistory fullhistory
ON fullhistory.userkeyid = FirstOccurenceHistory.firsttimeuserkeyid
AND DATE(fullhistory.dateCreated) > FirstOccurenceHistory.firstOccurrenceDate;
You overengineered it. How about:
select f1, f2, etc, count(*) records
from loginhistory join other tables as necessary
where datecreated >= date('2013-10-26')
group by f1, f2, etc
having count(*) > 1
Edit starts here
To restrict this to those who logged in for the first time on or after that date, add the following to the from clause of the above query
join (select useridkey userid, min(datecreated) mindate
from loginhistory
group by useridkey
having min(datecreated) >= date('2013-10-26')
) temp on userid = useridkey

SQL Query to get the last set of distinct records with some conditions

I have the following table:
I'm trying to find a way to get the records for those customers that have expired, and then update the table accordingly (by update I mean add an a new record with entry 'SERVICE EXPIRED' with the customer_id of the relevant customer).
If you look at the bottom of the table, you will notice two records with the entry 'SERVICE EXPIRED' for already existing customers (customer_id 11 and 16).
I'm looking for a SQL Query that will:
Get the last set of distinct records by customer_id
Exclude records for the same customer_id from the resulting resultset that have the entry 'SERVICE EXPIRED' or status_id of 2 appearing later on in the table
If I use the following:
SELECT MAX(id) FROM mytable WHERE status_id != '2' AND expiry < '2012-12-26 19:00:00' GROUP BY customer_id
It will return ids 1, 11, 13, and 16. However, I don't want ids 11 and 16 because the expiry status has already been noted later on in the table (see the last two records of the table), and id 1 has been renewed as can be seen with an updated expiry date in id 3 later. All I want is id 13 because that is the only expired record that does not have a 'SERVICE EXPIRED' entry that appears later in the table.
I'm looking for a SQL Query that will enable me capture this requirement.
Thanks in advance
After some fiddling around I managed to come up with a solution:
SELECT MAX(id)
FROM mytable
WHERE status_id != '2'
AND expiry < '2012-12-26 19:00:00'
AND customer_id NOT IN (SELECT MAX(customer_id) FROM mytable WHERE status_id = '2' GROUP BY customer_id)
GROUP BY customer_id
Thanks #JupiterP5 for pointing me in the right direction.
Regards,
Your requirement is equivalent to finding "n" records after the last expiry on a record. The following query returns all records after the last expiry for a given customer:
select t.*
from t join
(select t.customer_id, MAX(id) as maxid
from t
where status_id = 2
) texp
on t.customer_id = texp.customer_id and
t.id > texp.maxid
By using variables cleverly, you can enumerate these to get the last "n". However, do you really need a fixed number? Why not all of them? Why not just one of them?
It's not efficient, but this should work.
SELECT MAX(id)
FROM mytable
WHERE status_id != '2'
AND expiry < '2012-12-26 19:00:00'
AND id NOT IN (SELECT id FROM mytable where status_id = 2)
GROUP BY customer_id
Edit: Missed the service renewed case. I'll update if I think of something.