I want to fetch my record from mysql db. I want to fetch second maximum date from the record. But i failed
Here is my code
You can use simply below query to get second max date in a table or with your requirement : -
select joiningDate from t_member order by joiningDate desc limit 1,1
Note that the schema setup, QueryA
and QueryB
are all just for visualization.
Whereas, QueryC
is the one for you to try with your data.
The reason this does not do a simple order
by and limit
that @Musa does is simple: you can have many rows with the second greatest date, not one. That is why is uses a variables for @grp and @prevdate to target the second group.
-- drop table specimenA;
create table specimenA
( mypk int auto_increment primary key,
id int not null, -- note, not autoinc or pk
theDate date not null,
title varchar(255) not null,
otherThing varchar(20) not null
-- etc
-- not other indexes whatsoever
);
-- truncate table specimenA
insert specimenA (id,theDate,title,otherThing) values
(170,'2007-09-19','whatever','whatever'),
(170,'2008-09-12','whatever','whatever'),
(170,'2010-01-15','whatever','whatever'),
(170,'2011-02-03','whatever','whatever'),
(170,'2012-06-26','whatever','whatever'),
(170,'2013-03-05','whatever','whatever'),
(170,'2014-06-25','whatever','whatever'),
(170,'2015-06-09','whatever','whatever'),
(917,'2009-10-14','whatever','whatever'),
(917,'2008-12-31','whatever','whatever'),
(109,'2010-04-26','whatever','whatever'),
(109,'2011-03-02','whatever','whatever'),
(109,'2012-06-25','whatever','whatever'),
(109,'2013-01-04','whatever','whatever'),
(109,'2014-03-28','whatever','whatever'),
(109,'2015-03-18','whatever','whatever'),
(1057,'2014-03-28','whatever','whatever'),
(1057,'2014-11-21','whatever','whatever'),
(1057,'2015-08-13','whatever','whatever');
set @rn:=0,@grp:=0,@prevdate:='';
select id,theDate,title,otherThing,
@rn:=@rn+1 as rownum,
@grp:=if(@prevdate=theDate,@grp,@grp+1) as descGrp,
@prevdate:=theDate as unused
from specimenA
order by theDate DESC -- **** Note this
-- DESC means greatest first, as is most-recent first for dates
+------+------------+----------+------------+--------+---------+------------+
| id | theDate | title | otherThing | rownum | descGrp | unused |
+------+------------+----------+------------+--------+---------+------------+
| 1057 | 2015-08-13 | whatever | whatever | 1 | 1 | 2015-08-13 |
| 170 | 2015-06-09 | whatever | whatever | 2 | 2 | 2015-06-09 |
| 109 | 2015-03-18 | whatever | whatever | 3 | 3 | 2015-03-18 |
| 1057 | 2014-11-21 | whatever | whatever | 4 | 4 | 2014-11-21 |
| 170 | 2014-06-25 | whatever | whatever | 5 | 5 | 2014-06-25 |
| 1057 | 2014-03-28 | whatever | whatever | 6 | 6 | 2014-03-28 |
| 109 | 2014-03-28 | whatever | whatever | 7 | 6 | 2014-03-28 |
| 170 | 2013-03-05 | whatever | whatever | 8 | 7 | 2013-03-05 |
| 109 | 2013-01-04 | whatever | whatever | 9 | 8 | 2013-01-04 |
| 170 | 2012-06-26 | whatever | whatever | 10 | 9 | 2012-06-26 |
| 109 | 2012-06-25 | whatever | whatever | 11 | 10 | 2012-06-25 |
| 109 | 2011-03-02 | whatever | whatever | 12 | 11 | 2011-03-02 |
| 170 | 2011-02-03 | whatever | whatever | 13 | 12 | 2011-02-03 |
| 109 | 2010-04-26 | whatever | whatever | 14 | 13 | 2010-04-26 |
| 170 | 2010-01-15 | whatever | whatever | 15 | 14 | 2010-01-15 |
| 917 | 2009-10-14 | whatever | whatever | 16 | 15 | 2009-10-14 |
| 917 | 2008-12-31 | whatever | whatever | 17 | 16 | 2008-12-31 |
| 170 | 2008-09-12 | whatever | whatever | 18 | 17 | 2008-09-12 |
| 170 | 2007-09-19 | whatever | whatever | 19 | 18 | 2007-09-19 |
+------+------------+----------+------------+--------+---------+------------+
And, taking the above select statement, and making it a derived table as alias inR
, nested:
set @rn:=0,@grp:=0,@prevdate:='';
select id,theDate,title,otherthing
from
( select id,theDate,title,otherThing,
@rn:=@rn+1 as rownum,
@grp:=if(@prevdate=theDate,@grp,@grp+1) as descGrp,
@prevdate:=theDate as unused
from specimenA
order by theDate DESC -- **** Note this
) inR
where descGrp=2;
+-----+------------+----------+------------+
| id | theDate | title | otherthing |
+-----+------------+----------+------------+
| 170 | 2015-06-09 | whatever | whatever |
+-----+------------+----------+------------+
And there is your second greatest date. Meaning second most-recent date.
So, taking your original select statement, same concept. The motivation for showing the above is simply this: InR
is just a Derived Table
, no more or less than your select statement that will become a Derived Table.
set @rn:=0,@grp:=0,@prevdate:='';
select client_id, cid, tid, aid, oid, opinion, notification_date,
ttitle, atitle, otitle, ltitle, stitle,
opinion_id, pcid, pr_client, address, liaison_one,
cityid, head_office_id, city, cname
from
( SELECT r.client_id as client_id,c.id as cid,t.id as tid,a.id as aid,o.id as oid,c.name as opinion, r.notification_date,
t.title as ttitle,a.title as atitle,o.title as otitle, l.title as ltitle, s.title as stitle,
pr.opinion_id, pc.id as pcid, pr.client_id as pr_client, pc.address, pc.liaison_one,
city.id as cityid, pc.head_office_id, city.city, pc.title as cname,
@rn:=@rn+1 as rownum,
@grp:=if(@prevdate=r.notification_date,@grp,@grp+1) as descGrp,
@prevdate:=r.notification_date as unused
FROM og_ratings r
LEFT join
(
select max(notification_date) notification_date,
client_id
from og_ratings
WHERE notification_date NOT IN (select max(notification_date) FROM og_ratings )
) r2
on r.notification_date = r2.notification_date
and r.client_id = r2.client_id
LEFT JOIN og_companies c
ON r.client_id = c.id
LEFT JOIN og_rating_types t
ON r.rating_type_id = t.id
LEFT JOIN og_actions a
ON r.pacra_action = a.id
LEFT JOIN og_outlooks o
ON r.pacra_outlook = o.id
LEFT JOIN og_lterms l
ON r.pacra_lterm = l.id
LEFT JOIN og_sterms s
ON r.pacra_sterm = s.id
LEFT JOIN pacra_client_opinion_relations pr
ON pr.opinion_id = c.id
LEFT JOIN pacra_clients pc
ON pc.id = pr.client_id
LEFT JOIN city
ON city.id = pc.head_office_id
WHERE r.client_id IN (SELECT opinion_id FROM pacra_client_opinion_relations WHERE client_id = 50)
order by r.notification_date DESC
) inR
where descGrp=2
QueryC is what you go with. As it is two statements
... you need to run them in that order with query, one for each, in that order, or use PHP multi-query and combine both in one call. That link in previous sentence was for mysqli, the concept is hereby revealed, modify accordingly.
It wasn't fun to read your query, but I think the problem is here:
LEFT JOIN (
SELECT max(notification_date) notification_date, client_id
FROM og_ratings
WHERE notification_date NOT IN (
SELECT max(notification_date)
FROM og_ratings
)
if you want the maximum date for every client you need to GROUP BY client_id:
SELECT client_id, max(notification_date) notification_date
FROM og_ratings
GROUP BY client_id
if you want the second maximum there are few options, I'm using this one which is easier to understand but it's not necessarily the most performant:
SELECT client_id, max(notification_date) notification_date
FROM og_ratings
WHERE
(client_id, notification_date) NOT IN (
SELECT client_id, max(notification_date)
FROM og_ratings GROUP BY client_id
)
GROUP BY client_id
third problem, you're using a LEFT JOIN which means that you will return all values from og_ratings regardless if they are the second maximum or not. Use INNER JOIN on this context:
SELECT
r.client_id,
c.id,
t.id,
..etc...
FROM
og_ratings r INNER JOIN (
SELECT client_id, max(notification_date) notification_2nd_date
FROM og_ratings
WHERE
(client_id, notification_date) NOT IN (
SELECT client_id, max(notification_date)
FROM og_ratings GROUP BY client_id
)
GROUP BY client_id
) r2
ON r.notification_date = r2.notification_2nd_date
AND r.client_id = r2.client_id
LEFT JOIN og_companies c ON r.client_id = c.id
LEFT JOIN og_rating_types t ON r.rating_type_id = t.id
LEFT JOIN og_actions a ON r.pacra_action = a.id
LEFT JOIN og_outlooks o ON r.pacra_outlook = o.id
LEFT JOIN og_lterms l ON r.pacra_lterm = l.id
LEFT JOIN og_sterms s ON r.pacra_sterm = s.id
LEFT JOIN pacra_client_opinion_relations pr ON pr.opinion_id = c.id
LEFT JOIN pacra_clients pc ON pc.id = pr.client_id
LEFT JOIN city ON city.id = pc.head_office_id
WHERE
r.client_id IN (
SELECT opinion_id FROM pacra_client_opinion_relations
WHERE client_id = 50
)
You can use ORDER BY DATE_COLUMN DESC LIMIT 1 OFFSET 1
. I have appended this code at end of the query:
SELECT
r.client_id,
c.id,
t.id,
a.id,
o.id,
c.name as opinion,
r.notification_date,
t.title as ttitle,
a.title as atitle,
o.title as otitle,
l.title as ltitle,
s.title as stitle,
pr.opinion_id,
pc.id,
pr.client_id as pr_client,
pc.address,
pc.liaison_one,
city.id,
pc.head_office_id,
city.city,
pc.title as cname
FROM og_ratings r
LEFT join (
select max(notification_date) notification_date,
client_id
from og_ratings
WHERE notification_date NOT IN (select max(notification_date) FROM og_ratings )
) r2
on r.notification_date = r2.notification_date
and r.client_id = r2.client_id
LEFT JOIN og_companies c
ON r.client_id = c.id
LEFT JOIN og_rating_types t
ON r.rating_type_id = t.id
LEFT JOIN og_actions a
ON r.pacra_action = a.id
LEFT JOIN og_outlooks o
ON r.pacra_outlook = o.id
LEFT JOIN og_lterms l
ON r.pacra_lterm = l.id
LEFT JOIN og_sterms s
ON r.pacra_sterm = s.id
LEFT JOIN pacra_client_opinion_relations pr
ON pr.opinion_id = c.id
LEFT JOIN pacra_clients pc
ON pc.id = pr.client_id
LEFT JOIN city
ON city.id = pc.head_office_id
WHERE
r.client_id IN (
SELECT opinion_id FROM pacra_client_opinion_relations WHERE client_id = 50
)
ORDER BY r.notification_date DESC # Add this line
LIMIT 1 offset 1 # and this line