Select max date and max time from query [duplicate] - mysql

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 5 years ago.
This is my current data in database.
========================================
id | IC |date |time |
1 | test |2017-07-27 |14:19:26 |
2 | test |2017-07-27 |14:20:26 |
3 | second |2017-07-28 |06:58:55 |
========================================
I want to get the maxdate and maxtime for each IC.
I tried:
SELECT id,pass_no,time_in,ic,date_in FROM `check_in`
WHERE date_in = (SELECT MAX(date_in) FROM check_in)
AND
time_in = (SELECT MAX(time_in) FROM check_in) GROUP BY IC
But it only return the last row data for me. The result I wanted is like
========================================
id | IC |date |time |
2 | test |2017-07-27 |14:20:26 |
3 | second |2017-07-28 |06:58:55 |
========================================

This will return the max date & time per ic:
select ic, max(date), max(time)
from check_in
group by ic

You can use a tuple and group by ic
SELECT id,pass_no,time_in,ic,date_in
FROM `check_in`
WHERE (date_in, time_in, ic) in (
SELECT MAX(date_in), max(time_id), ic
FROM check_in
GROUP BY id)

This should work
select max(time),date,id
from (select max(date) as date,time,id from check-in group by time,id )
group by date,id;

Did you try with "OR" condition insteads "AND"?

Related

MySQL - Count unique users each day considering all previous days

I would like to count how many new unique users the database gets each day for all days recorded.
There will not be any duplicate ids per day, but there will be duplicates over multiple days.
If my table looks like this :
ID | DATE
---------
1 | 2022-05-21
1 | 2022-05-22
2 | 2022-05-22
1 | 2022-05-23
2 | 2022-05-23
1 | 2022-05-24
2 | 2022-05-24
3 | 2022-05-24
I would like the results to look like this :
DATE | NEW UNIQUE IDs
---------------------------
2022-05-21 | 1
2022-05-22 | 1
2022-05-23 | 0
2022-05-24 | 1
A query such as :
SELECT `date` , COUNT( DISTINCT id)
FROM tbl
GROUP BY DATE( `date` )
Will return the count per day and will not take into account previous days.
Any assistance would be appreciated.
Edit : Using MySQL 8
The user is new when the date is the least date for this user.
So you need in something like
SELECT date, COUNT(new_users.id)
FROM calendar
LEFT JOIN ( SELECT id, MIN(date) date
FROM test
GROUP BY id ) new_users USING (date)
GROUP BY date
calendar is either static or dynamically generated table with needed dates list. It can be even SELECT DISTINCT date FROM test subquery.
Start with a subquery showing the earliest date where each id appears.
SELECT MIN(`date`) `firstdate`, id
FROM tbl
GROUP BY id
Then do your count on that subquery. here.
SELECT firstdate, COUNT(*)
FROM (
SELECT MIN(`date`) `firstdate`, id
FROM tbl
GROUP BY id
) m
GROUP BY firstdate
That gives you what you want.
But it doesn't have rows for the dates where no new user ids first appeared.
Only count (and sum) the rows where the left join fails:
SELECT
m1.`DATE` ,
sum(CASE WHEN m2.id is null THEN 1 ELSE 0 END) as C
FROM mytable m1
LEFT JOIN mytable m2 ON m2.`DATE`<m1.`DATE` AND m2.ID=m1.ID
GROUP BY m1.`DATE`
see: DBFIDDLE

MySQL - select rows under an ID, group by column value that has the latest timestamp

Table:
----------------------------------------------------
ID | field_name | field_value | timestamp
----------------------------------------------------
2 | postcode | LS1 | 2016-11-09 16:45:15
2 | age | 34 | 2016-11-09 16:45:22
2 | job | Scientist | 2016-11-09 16:45:27
2 | age | 38 | 2016-11-09 16:46:40
7 | postcode | LS5 | 2016-11-09 16:47:05
7 | age | 24 | 2016-11-09 16:47:44
I wonder if anyone could give me a few pointers, based on the above data, I would like to query by ID 2, return a row for each unique field_name (if more than one row exists under the same id with the same field_name then just return the row with the latest timestamp).
I have managed to almost achieve this by grouping the field_name, which will return a list of unique rows but not necessarily the latest row.
SELECT * FROM fragment WHERE (id = :id) GROUP BY field_name
I would really be grateful for any pointers on what exactly I should do here, and how I could fit something along the lines of MAX(timestamp) in this query,
Many thanks!
Consider you first need a set of data for each ID, FieldName with the max time stamp. (generate that set) as an inline view (B below). Then, join this set (B) back to your base set allowing the inner join to eliminate the unwanted rows.
SELECT A.ID, A.field_name, A.field_value, A.timestamp
FROM Table A
INNER JOIN (SELECT ID, field_name, MAX(timestamp) TS
FROM table
GROUP BY ID, field_name) B
on A.ID = B.ID
and A.field_name = B.field_name
and A.timestamp = B.TS
Outside of MySQL this could be done using window/analytical functions as you would be able to assign a row number to each record and eliminate those > 1 something like....
SELECT B.*
FROM (SELECT A.ID
, A.field_name
, A.field_Vale
, A.timestamp
, Rownumber() over (Order by A.timestamp Desc) RN
FROM Table A ) B
WHERE B.RN = 1
or using a cross apply with a limit or top.
The Simpliest way to do:
SELECT *
FROM fragment fra1
WHERE (id = :id)
and timestamp = (select max(timestamp)
from fragment fra2
where fra2.id = fra1.id
and fra2.field_name = fra1.field_name)
GROUP BY field_name

MySQL selecting latest occurrences of a GROUP BY'd field [duplicate]

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 6 years ago.
I have a table that has a non-unique id, id, a status, status (which I'm trying to get), and a timestamp of when it was inserted, inserted. I need to select the most recent occurrence of each id ordered by the id. I have the following table ordered by inserted:
id | status | inserted
------------------------------------
4 | approved | 2016-08-09 15:51:52
5 | denied | 2016-08-09 15:52:36
5 | pending | 2016-08-09 15:55:05
The results I need are:
id | status | inserted
------------------------------------
4 | approved | 2016-08-09 15:51:52
5 | pending | 2016-08-09 15:55:05
I have the following SELECT:
SELECT * FROM table
GROUP BY id
ORDER BY inserted
and I'm getting these results:
id | status | inserted
------------------------------------
4 | approved | 2016-08-09 15:51:52
5 | denied | 2016-08-09 15:52:36
The solution is probably an easy one, but I've racked my brain on this long enough trying things such as inner selects and whatnot. Any help would be appreciated.
EDIT:
I had to use the third option from the linked duplicate question to get the results I expected (the one with the LEFT JOIN). I assume it was because I was using a DATETIME type, but I'm unsure.
select t.*
from
<T> t inner join
(select id, max(inserted) as max_inserted from <T> group by id) as m
on m.id = t.id and m.max_inserted = t.inserted
or
select
id,
(
select status from <T> t2
where t2.id = t.id and t2.inserted = max_inserted
) as status,
max(inserted) as max_inserted
from <T>
group by id
You can try searching for "mysql latest per group" or something like that for alternatives more specific to MySQL.
If you want the most recent record for each id, then don't use group by. Instead:
select t.*
from table t
where t.inserted = (select max(t2.inserted) from table t2 where t2.id = t.id);

Finding a single row for an identity [duplicate]

This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed 8 years ago.
I have a table that has multiple values for an identity, and I want to find just one row for each identity where the date field is the newest and then if there is still duplicates just select the one with the lowest id.
My table looks kine of like this:
UniqueID | CustomerId | Name | Address | InspDate
1 1 Bob 123 2013/08/05 00:00:00
2 1 Bob 123 2013/08/05 00:00:00
3 1 Bob 123 2013/03/01 00:00:00
So I only want the row with uniqueid of 1 to show up to show up in this example.
Also I want to limit it to only Customers with inspdates done within the last year if that is possible.
SELECT t.*
FROM
yourtable t INNER JOIN (
SELECT MIN(UniqueID) as Min_ID
FROM
yourtable t1 INNER JOIN (SELECT CustomerID, MAX(InspDate) Max_date
FROM yourtable
GROUP BY CustomerID) m
ON t1.CustomerID=m.CustomerID AND t1.InspDate=m.Max_date
GROUP BY t1.CustomerID) mi
ON t.UniqueID = mi.Min_ID
Please see fiddle here.

MySQL - Exclude rows from Select based on duplication of two columns

I am attempting to narrow results of an existing complex query based on conditional matches on multiple columns within the returned data set. I'll attempt to simplify the data as much as possible here.
Assume that the following table structure represents the data that my existing complex query has already selected (here ordered by date):
+----+-----------+------+------------+
| id | remote_id | type | date |
+----+-----------+------+------------+
| 1 | 1 | A | 2011-01-01 |
| 3 | 1 | A | 2011-01-07 |
| 5 | 1 | B | 2011-01-07 |
| 4 | 1 | A | 2011-05-01 |
+----+-----------+------+------------+
I need to select from that data set based on the following criteria:
If the pairing of remote_id and type is unique to the set, return the row always
If the pairing of remote_id and type is not unique to the set, take the following action:
Of the sets of rows for which the pairing of remote_id and type are not unique, return only the single row for which date is greatest and still less than or equal to now.
So, if today is 2011-01-10, I'd like the data set returned to be:
+----+-----------+------+------------+
| id | remote_id | type | date |
+----+-----------+------+------------+
| 3 | 1 | A | 2011-01-07 |
| 5 | 1 | B | 2011-01-07 |
+----+-----------+------+------------+
For some reason I'm having no luck wrapping my head around this one. I suspect the answer lies in good application of group by, but I just can't grasp it. Any help is greatly appreciated!
/* Rows with exactly one date - always return regardless of when date occurs */
SELECT id, remote_id, type, date
FROM YourTable
GROUP BY remote_id, type
HAVING COUNT(*) = 1
UNION
/* Rows with more than one date - Return Max date <= NOW */
SELECT yt.id, yt.remote_id, yt.type, yt.date
FROM YourTable yt
INNER JOIN (SELECT remote_id, type, max(date) as maxdate
FROM YourTable
WHERE date <= DATE(NOW())
GROUP BY remote_id, type
HAVING COUNT(*) > 1) sq
ON yt.remote_id = sq.remote_id
AND yt.type = sq.type
AND yt.date = sq.maxdate
The group by clause groups all rows that have identical values of one or more columns together and returns one row in the result set for them. If you use aggregate functions (min, max, sum, avg etc.) that will be applied for each "group".
SELECT id, remote_id, type, max(date)
FROM blah
GROUP BY remote_id, date;
I'm not whore where today's date comes in, but assumed that was part of the complex query that you didn't describe and I assume isn't directly relevant to your question here.
Try this:
SELECT a.*
FROM table a INNER JOIN
(
select remote_id, type, MAX(date) date, COUNT(1) cnt from table
group by remote_id, type
) b
WHERE a.remote_id = b.remote_id,
AND a.type = b.type
AND a.date = b.date
AND ( (b.cnt = 1) OR (b.cnt>1 AND b.date <= DATE(NOW())))
Try this
select id, remote_id, type, MAX(date) from table
group by remote_id, type
Hey Carson! You could try using the "distinct" keyword on those two fields, and in a union you can use Count() along with group by and some operators to pull non-unique (greatest and less-than today) records!