I have student and event tables linked by sid.
CREATE TABLE `students` (
`sid` int(8) NOT NULL COMMENT 'use',
`active` enum('Yes','No','vac','Grad') NOT NULL DEFAULT 'Yes',
`name` varchar(130) DEFAULT NULL,
`bus` varchar(130) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `students` (`sid`, `LEFT(name, 2)`, `bus`) VALUES
(51, 'Me', 'BusA'),
(52, 'Hi', 'BusA'),
(59, 'An', 'BusA'),
(70, 'Mi', 'BusB'),
(100, 'Yu', 'BusB');
CREATE TABLE `STATevent` (
`eventid` int(24) NOT NULL,
`sid` int(4) NOT NULL,
`date` datetime NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`level` enum('absent','bus') CHARACTER SET utf8 NOT NULL,
`color` varchar(10) NOT NULL,
`Percent` tinyint(5) NOT NULL,
`note` varchar(266) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `STATevent` (`eventid`, `sid`, `date`, `created`, `level`, `color`, `Percent`, `note`) VALUES
(43, 59, '2022-11-30 21:17:04', '2022-11-28 12:17:04', 'bus', 'red', 100, '');
The student can select not to get bus service, which shows as an entry (like eventid 43 above). I can get the list of 'bus students', along with an id to show who cancelled service and who hasn't.
SELECT C.name, C.sid, O.sid AS 'bid', C.bus FROM students C
LEFT JOIN STATevent O ON C.sid = O.sid
WHERE C.bus LIKE 'Bus%' AND C.active = 'Yes' ;
However, when I try to limit where with the date, the result shows only the one who cancelled service.
SELECT C.name, C.sid, O.sid AS 'bid', C.bus FROM students C
LEFT JOIN STATevent O ON C.sid = O.sid
WHERE C.bus LIKE 'Bus%' AND C.active = 'Yes' AND O.date LIKE '2022-11-29%';
How can I add this limiter and get the full results like the first query?
Thanks in advance for your help.
You may move the restriction on the event date to the ON clause of the left join:
SELECT c.name, c.sid, o.sid AS bid, c.bus
FROM students c
LEFT JOIN STATevent o
ON o.sid = c.sid AND
DATE(o.date) = '2022-11-29'
WHERE c.bus LIKE 'Bus%' AND c.active = 'Yes';
For students who did not cancel service, the bid would be reported as null.
You want to show all students that use a bus servvice, but exclude those that opt out for a certain date. You can use NOT EXISTS or NOT IN to do this lookup.
SELECT *
FROM `students`
WHERE bus LIKE 'Bus%' AND active = 'Yes'
AND sid NOT IN
(
SELECT sid
FROM `STATevent`
WHERE DATE(date) = DATE '2022-11-30'
)
ORDER BY sid;
If you want to show all potential bus service users instead with a flag whether they attend that day or not, you can move the condition to the select clause:
SELECT s.*
sid IN
(
SELECT sid
FROM `STATevent`
WHERE DATE(date) = DATE '2022-11-30'
) AS opt_out
FROM `students` s
WHERE bus LIKE 'Bus%' AND active = 'Yes'
ORDER BY sid;
Demo: https://dbfiddle.uk/TxyzF564
Related
I am trying to list all competitions in a table, whether a user has entered each competition, and the total number of entries for each competition.
Here are the tables:
CREATE TABLE `competition` (
`competitionID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` char(255) NOT NULL DEFAULT '',
`description` varchar(750) NOT NULL DEFAULT '',
`startDate` date DEFAULT NULL,
`endDate` date DEFAULT NULL,
`isLive` tinyint(1) NOT NULL,
PRIMARY KEY (`competitionID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `competition` (`competitionID`, `name`, `description`,
`startDate`, `endDate`, `isLive`)
VALUES
(1,'Win a car','Win a really cool car!','2018-04-01 09:30:27','2019-04-01 09:30:27',1),
(2,'Another competition','Win something even better!','2018-04-01 09:30:27','2019-04-01 09:30:27',1);
CREATE TABLE `competition_entrant` (
`competitionEntrantID` int(11) NOT NULL AUTO_INCREMENT,
`userID` int(11) NOT NULL,
`competitionID` int(11) NOT NULL,
PRIMARY KEY (`competitionEntrantID`),
UNIQUE KEY `userID` (`userID`,`competitionID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `competition_entrant` (`competitionEntrantID`, `userID`,
`competitionID`)
VALUES
(1,1,1),
(2,1,2),
(3,2,1);
So in this example user with id 1 has entered both competitions and user with id 2 has entered competition with id 1.
Here is my query.
SELECT
`c`.`name`,
COUNT(`ce1`.`userID`) AS 'hasEnteredCompetition',
COUNT(`ce2`.`userID`) AS 'totalEntries'
FROM competition c
LEFT JOIN `competition_entrant` `ce1` ON `c`.`competitionID` =
`ce1`.`competitionID`
AND `ce1`.`userID` = 2
LEFT JOIN `competition_entrant` `ce2` ON `c`.`competitionID` =
`ce2`.`competitionID`
GROUP BY (c.competitionID);
The problem is that hasEnteredCompetition is showing the total number of entries rather than just 1 for the user entered i.e. the count for that user.
Can anyone tell me what I'm doing wrong here?
You are joining to the competition_entrant table twice, so the user "2" entry is being pulled twice. You can see it this way:
SELECT C.COMPETITIONID,C.NAME,CE1.USERID,CE1.COMPETITIONID
FROM COMPETITION C
LEFT JOIN COMPETITION_ENTRANT CE1 ON C.COMPETITIONID = CE1.COMPETITIONID AND CE1.USERID = 2
LEFT JOIN COMPETITION_ENTRANT CE2 ON C.COMPETITIONID = CE2.COMPETITIONID
1 Win a car 2 1
2 Another competition null null
1 Win a car 2 1
You could add a count distinct to your query like this:
select C.NAME,C.COMPETITIONID,
COUNT(DISTINCT CE1.USERID) as "hasEnteredCompetition",
COUNT(CE2.USERID) as "totalEntries"
from COMPETITION C
left join COMPETITION_ENTRANT CE1 on C.COMPETITIONID = CE1.COMPETITIONIDand CE1.USERID = 2
left join COMPETITION_ENTRANT CE2 on C.COMPETITIONID = CE2.COMPETITIONID
group by (C.NAME,C.COMPETITIONID)
If I understand you correctly (a "expected result" would be nice) you only need to list all competitions, the number of users that entered and if anyone entered at all, right? Then you do not need the second left join, you could go with something like this:
select
competition.competitionID,
competition.name,
case when count(competition.competitionID) > 0 THEN 'yes' ELSE 'no' END AS hasEnteredCompetition,
count(competition.competitionID) AS 'totalEntries'
from competition
left join competition_entrant ON competition.competitionID = competition_entrant.competitionID
group by competitionId, name
This question already has answers here:
Join tables with SUM issue in MYSQL
(2 answers)
Closed 5 years ago.
I am on Mysql version 5.5. I have two tables - product, ordr.
CREATE TABLE `product` (
`id` int(11) NOT NULL,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ordr` (
`id` int(11) NOT NULL,
`product_id` varchar(45) DEFAULT NULL,
`status` varchar(45) DEFAULT NULL,
`qty` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Here is how they are populated -
insert into product values (20, 'pen');
insert into ordr values (100, 20, 'queue', 5);
insert into ordr values (110, 20, 'queue', 5);
insert into ordr values (120, 20, 'pending', 10);
insert into ordr values (130, 20, 'pending', 10);
insert into ordr values (140, 20, 'pending', 10);
I want to get the total quantity of products that are in two different statuses. For the test data above data, I want to see 10 for queue quantity and 30 for pending quantity.
When I run
select p.name, sum(o.qty) as queue_qty, sum(o2.qty) as pending_qty
from product p
left outer join ordr o on o.product_id = p.id and o.status = 'queue'
left outer join ordr o2 on o2.product_id = p.id and o2.status = 'pending'
where p.id = 20;
I get
name - pen
queue_qty - 30
pending_qty - 60
Can someone help me fix this SQL?
You need to aggregate the information before it's joined. Since you have two 1-n relationships, your join logic is duplicating information.
select
p.name
, o.qty as qty_queue
, o2.qty as qty_pending
from
product p
join (
select
product_id
, sum(qty) as qty
from
ordr
where
ordr.status = 'queue'
group by
product_id
) o
on p.id = o.product_id
join (
select
product_id
, sum(qty) as qty
from
ordr
where
ordr.status = 'pending'
group by
product_id
) o2
on p.id = o2.product_id
group by
p.name
Okay, so I have 3 tables:
users
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(11) NOT NULL,
`user_username` varchar(25) NOT NULL,
`user_email` varchar(100) NOT NULL,
`user_password` varchar(255) NOT NULL,
`user_enabled` int(1) NOT NULL DEFAULT '1',
`user_staff` varchar(15) NOT NULL DEFAULT '',
`user_account_type` varchar(20) NOT NULL DEFAULT '0',
`user_registerdate` date NOT NULL,
`user_twofactor` int(11) NOT NULL DEFAULT '0',
`user_twofackey` varchar(255) NOT NULL,
`user_forgot_email_code` varchar(255) NOT NULL,
`user_emailverified` varchar(25) NOT NULL DEFAULT 'unverified',
`user_banned` varchar(25) NOT NULL DEFAULT 'unbanned',
`user_has_avatar` int(11) NOT NULL DEFAULT '0',
`user_has_banner` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`user_id`, `user_username`, `user_email`, `user_password`, `user_enabled`, `user_staff`, `user_account_type`, `user_registerdate`, `user_twofactor`, `user_twofackey`, `user_forgot_email_code`, `user_emailverified`, `user_banned`, `user_has_avatar`, `user_has_banner`) VALUES
(1, 'fhfhfhf', 'lol#gmail.com', 'removed', 1, 'admin', 'Business', '2015-07-21', 0, '0', '0', 'unverified', 'unbanned', 1, 0);
company
CREATE TABLE IF NOT EXISTS `company` (
`company_id` int(11) NOT NULL,
`company_name` varchar(100) NOT NULL,
`company_user` int(11) NOT NULL,
`company_enabled` varchar(50) NOT NULL DEFAULT 'enabled',
`company_has_avatar` int(5) NOT NULL DEFAULT '0',
`company_has_banner` int(5) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `company`
--
INSERT INTO `company` (`company_id`, `company_name`, `company_user`, `company_enabled`, `company_has_avatar`, `company_has_banner`) VALUES
(1, 'Rad', 3, 'enabled', 0, 0);
training_company
CREATE TABLE IF NOT EXISTS `training_company` (
`training_company_id` int(11) NOT NULL,
`training_company_name` varchar(100) NOT NULL,
`training_company_user` int(11) NOT NULL,
`training_company_enabled` varchar(50) NOT NULL DEFAULT 'enabled',
`training_company_has_avatar` int(5) NOT NULL DEFAULT '0',
`training_company_has_banner` int(5) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `training_company`
--
INSERT INTO `training_company` (`training_company_id`, `training_company_name`, `training_company_user`, `training_company_enabled`, `training_company_has_avatar`, `training_company_has_banner`) VALUES
(1, '123', 3, 'enabled', 0, 0),
(2, '123', 3, 'enabled', 0, 0),
(3, '123', 3, 'enabled', 0, 0);
Each have a profile, that have an incrementing id, so will have the same id, Iam just defining they via type, so user would be user, training would be training and company would be company, I am allowing a user to follow either one.
SQL
SELECT * FROM timeline_status
LEFT JOIN users
ON timeline_status.timeline_status_user = users.user_id
LEFT JOIN timeline_likes
ON timeline_status.timeline_status_id = timeline_likes.timeline_likes_main_status
LEFT JOIN friends
ON timeline_status.timeline_status_user = friends.friends_friend
LEFT JOIN user_personal_information
ON timeline_status.timeline_status_user = user_personal_information.user_personal_information_user
LEFT JOIN following
ON timeline_status.timeline_status_user = following.following
WHERE timeline_status_enabled = 'enabled'
AND timeline_status.timeline_status_type = 'user'
AND (timeline_status.timeline_status_user = :status_user
OR friends.friends_user = :friend_user)
AND (timeline_status_privacy = 'onlyme'
AND timeline_status_user = :status_user2
OR timeline_status_privacy = 'public'
OR timeline_status_privacy = 'private')
GROUP BY timeline_status_id
ORDER BY timeline_status_date DESC
LIMIT :start, :end
So I'd want to select from users if type = user, and row exists in followers and/or friends, select from companies or training from followers if type = company or training.
My status have the company/user/training id, and the type, so I know which table to select the 'user from'
my following table;
CREATE TABLE IF NOT EXISTS `following` (
`following_id` int(11) NOT NULL,
`following_user` int(11) NOT NULL,
`following_type` varchar(50) NOT NULL,
`following` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `following`
--
INSERT INTO `following` (`following_id`, `following_user`, `following_type`, `following`) VALUES
(5, 3, 'company', 14),
(8, 3, 'training', 1);
timeline status:
CREATE TABLE IF NOT EXISTS `timeline_status` (
`timeline_status_id` int(11) NOT NULL,
`timeline_status_user` int(11) NOT NULL,
`timeline_status_privacy` varchar(25) NOT NULL DEFAULT 'public',
`timeline_status_type` varchar(25) NOT NULL DEFAULT 'user',
`timeline_status_post` text NOT NULL,
`timeline_status_date` datetime NOT NULL,
`timeline_status_enabled` varchar(25) NOT NULL DEFAULT 'enabled'
) ENGINE=InnoDB AUTO_INCREMENT=123 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `timeline_status`
--
INSERT INTO `timeline_status` (`timeline_status_id`, `timeline_status_user`, `timeline_status_privacy`, `timeline_status_type`, `timeline_status_post`, `timeline_status_date`, `timeline_status_enabled`) VALUES
(98, 3, 'private', 'user', 'hello', '2015-10-02 16:29:48', 'enabled'),
(99, 3, 'onlyme', 'user', 'yo', '2015-10-02 16:29:56', 'enabled'),
(100, 3, 'public', 'user', 'fghyjt', '2015-10-02 17:51:28', 'enabled'),
(101, 1, 'private', 'training', 'teest..', '2015-10-03 14:26:45', 'enabled'),
(102, 15, 'public', 'company', 'hello', '2015-10-06 13:32:30', 'enabled');
So how can I do it so if the following type = company select from company, if following tye = training select from training, and if following type = user, keep the sql how it is at the moment. Because at the moment, I am following a company with the id of 1, but there's a user with an id of 1 too, so I am getting their statuses.
Your best bet would be to use the UNION operator to mix them all in 1 table, and then query based on type. For instance, you could do something like this :
SELECT f.*,
t.training_company_name as name,
null as staff,
t.training_company_enabled as enabled,
t.training_company_has_banner as banner,
t.training_company_has avatar as avatar
FROM following f
INNER JOIN training_company t on f.following_user = t.training_company_user AND f.following_type='training'
UNION ALL
SELECT f.*,
c.company_name as name,
null as staff,
c.company_enabled as enabled,
c.company_has_banner as banner,
c.company_has avatar as avatar
FROM following f
INNER JOIN company c on f.following_user = c.company_user AND c.following_type='company'
UNION ALL
SELECT f.*,
u.user_username as name,
u.user_staff as staff,
u.user_enabled as enabled,
u.user_has_banner as banner,
u.user_has avatar as avatar
FROM following f
INNER JOIN users u on f.following_user = c.company_user AND f.following_type='user'
And from there you will have a derived table/view that will look like
V_followers(timeline_status_id, timeline_status_user, timeline_status_privacy, timeline_status_type, timeline_status_post, timeline_status_date, timeline_status_enabled, name, staff, enabled, banner, avatar).
I'm not 100% certain the syntax is MySql-correct though, but the idea remains the same.
I think you will need another variable to tell you the type in addition to the user id. Then you can wrap both up in a CASE statement, like so:
WHERE
CASE WHEN type = 'USER' THEN timeline_status.timeline_status_user = id
WHEN type = 'FRIENDS' THEN friends.friends_user = id
WHEN type = 'FOLLOWING' THEN following.user = id
END
In your question you actually ask few questions)
1) And company and training_company have user, that's why you can join this tables,
left join will takes only needed rows and from appropriate tables,
and with case you can select needed field:
select
u.user_id, u.user_account_type,
case when u.user_account_type = 'Business' then c.company_name
else tc.training_company_name
end as name_of_company
from users u
left join company as c on u.user_id = c.company_user
left join training_company as tc on u.user_id = tc.training_company_user
;
2) Table following contains and users and companies that's why you can do the same:
select
f.following_user,
f.following_type,
case
when f.following_type = 'company' then c.company_name
when f.following_type = 'training' then tc.training_company_name
else u.user_username
end as name
from following f
left join users u on f.following_user = u.user_id
-- here you can add inner joins to followers, friends etc
left join company as c on f.following_user = c.company_user
left join training_company as tc on f.following_user = tc.training_company_user
;
3) I think your schema pretty simple
and i'm sure that you can use joins to achieve your desires.
I would like emphasize one moment
if you have choice: user or company etc - use left join,
if you have restrictions users with followers or friends etc - use inner join... (it should work faster)...
Hope i correctly understood you, and this info will help you!
It seems like you have a situation whereby you have the concept of an entity that can post statuses, and has other information relevant to that.
These entities come in three forms; user, company, training_company. Each of these forms may have more specific sub details.
Have you considered placing all the entity info in one table:
entity - id, type, name, enabled, banner, avatar
Then implementing a has_one relationship to any information relevant to the sub_type:
user - entity_id, ... user specific fields
company - entity_id, .. company specific fields
training_company - entity_id .. training company specific fields
Usually you will be doing one of the following:
aggregate stats regarding entities/statuses - select from entity
lists of statuses - select from entity
aggregate stats regarding one specific type - select from type_table join entity
list inc. detail of one specific type - select from type_table join entity
details of one entity - select from type_table join entity
In the rare case of needing to display full details of a list of entities you can either use a UNION query or just run one query for the entities and then 3 queries on the sub_types WHERE entity_id IN (pulled entity ids).. this data is often paginated anyway, so the performance should be good enough.
We have used this structure in our projects to good effect, be aware it will require more complicated CRUD operations.
How can I select a row from another table based on the sum of column from the left table
SELECT Group_concat(c.cartid SEPARATOR ',') AS CartIDs,
Sum(c.grandtotal) AS Sum,
r.percentage
FROM carts c
LEFT JOIN rebates r
ON Sum(c.grandtotal) >= r.fromamountpurchased
AND Sum(c.grandtotal) <= r.toamountpurchased
WHERE c.ispaid = '1'
AND c.addedtorebates = '0'
GROUP BY c.customerid
But this doesn't work. I also tried HAVING also doesn't work.
Is it possible in one query?
Thanks!
UPDATE:
CREATE TABLE IF NOT EXISTS `carts` (
`CartID` bigint(20) NOT NULL AUTO_INCREMENT,
`CustomerID` bigint(20) NOT NULL,
`GrandTotal` decimal(10,2) NOT NULL,
`IsPaid` enum('0','1','2') NOT NULL,
`AddedToRebates` enum('0','1') NOT NULL,
PRIMARY KEY (`CartID`)
)
INSERT INTO `carts` (`CartID`, `CustomerID`, `GrandTotal`, `IsPaid`,
`AddedToRebates`, ) VALUES
(71, 28, '57450.00', '1', '0' ),
(73, 28, '57450.00', '1', '0');
CREATE TABLE IF NOT EXISTS `rebates` (
`RebateID` bigint(20) NOT NULL AUTO_INCREMENT,
`Percentage` varchar(255) NOT NULL COMMENT 'in %',
`FromAmountPurchased` decimal(10,2) NOT NULL,
`ToAmountPurchased` decimal(10,2) NOT NULL,
`CashEquivalent` decimal(10,2) NOT NULL,
PRIMARY KEY (`RebateID`)
)
INSERT INTO `rebates` (`RebateID`, `Percentage`, `FromAmountPurchased`,
`ToAmountPurchased`, `CashEquivalent`) VALUES
(1, '5', '50000.00', '69999.00', '3000.00'),
(2, '10', '70000.00', '79999.00', '5000.00'),
(3, '15', '80000.00', '89999.00', '6000.00'),
(4, '20', '90000.00', '99999.00', '7000.00'),
(5, '25', '100000.00', '150000.00', '8000.00'),
(6, '0', '0.00', '49999.00', '0.00');
Try this:
select q1.CartIDs, q1.total, r.percentage
from
(select group_concat(c.cartid) as CartIDs, sum(c.grandtotal) as total
from carts c
where c.ispaid = '1'
and c.addedtorebates = '0'
group by c.customerid ) q1
left join rebates r
on q1.total >= r.fromamountpurchased
and q1.total <= r.toamountpurchased
Here is a demo fiddle for you: http://sqlfiddle.com/#!9/d27f5/3
You cannot use aggregate functions like SUM() in the join predicate, so in this instance, a subquery is useful
You can achieve your result with a sub query. Please note that this sub query requires an additional scan of carts.
SELECT GROUP_CONCAT(c.CartID SEPARATOR ',') AS CartIDs, SUM(c.GrandTotal) as Sum, r.Percentage
FROM carts c
INNER JOIN (
SELECT SUM(GrandTotal) as grandTotal, CustomerID
FROM carts
GROUP BY CustomerID
) cSums ON cSums.CustomerID = c.CustomerID
LEFT JOIN rebates r ON cSums.grandTotal >= r.FromAmountPurchased AND cSums.grandTotal <= r.ToAmountPurchased
WHERE c.IsPaid = '1' AND c.AddedToRebates = '0' GROUP BY c.CustomerID
I have two table one is 'tb_student' and other is 'tb_fees'
create query for 'tb_student'
CREATE TABLE `tb_student` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`class` varchar(255) NOT NULL,
`created_on` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
)
create query for 'tb_fees'
CREATE TABLE `tb_fees` (
`id` int(11) NOT NULL auto_increment,
`email` varchar(255) NOT NULL,
`amount` varchar(255) NOT NULL,
`created_on` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
)
In first table i am storing the student details and in other table storing the fees details
I want to select student details from 'tb_student' and last add fee from 'tb_fees' only for those student which are in class 6
so i tried this
SELECT *
FROM tb_student s INNER JOIN
tb_fees f on
s.email =f.email
WHERE s.class = 6 GROUP BY s.email ORDER BY f.created_on DESC
This will give result only the first created how to get last created values
fees table
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (5,'ram#gmail.com','5000','2013-05-01 14:20:15');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (6,'Sam#gmail.com','5000','2013-05-02 14:20:23');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (7,'jak#gmail.com','5000','2013-05-03 14:20:30');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (8,'Sam#gmail.com','5000','2013-05-29 14:20:35');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (9,'ram#gmail.com','5000','2013-05-30 14:20:39');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (10,'jak#gmail.com','5000','2013-05-30 14:36:13');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (11,'rose#gmail.com','5000','2013-05-30 14:36:15');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (12,'nim#gmail.com','5000','2013-05-30 14:36:15');
Student table values
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (5,'Ram','ram#gmail.com','6','2013-04-30 14:00:56');
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (6,'Sam','Sam#gmail.com','6','2013-03-30 14:01:30');
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (7,'Nimmy','nim#gmail.com','7','2013-04-30 13:59:59');
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (8,'jak','jak#gmail.com','6','2013-03-30 14:07:32');
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (9,'rose','rose#gmail.com','5','2013-04-30 14:07:51');
Thank you
To get the latest fees something like this:-
SELECT s.* , f.*
FROM tb_student s
INNER JOIN
(SELECT email, MAX(created_on) AS created_on
FROM tb_fees
GROUP BY email) Sub1
ON s.email = sub1.email
INNER JOIN tb_fees f
ON s.email = f.email AND Sub1.created_on = f.created_on
WHERE s.class = 6
By the way, you probably want indexes on the email fields (or better, use the tb_student id field on the tb_fees table instead of the email field and index it)
Use MAX group function
SELECT s.*, f.amount,MAX(f.created_on)
FROM tb_student s
INNER JOIN
tb_fees f
ON
s.email =f.email
WHERE s.class = 6
GROUP BY s.email