How query with data functions in group by ca be optimized - mysql

i have a query as given below
SELECT MONTHNAME( f.receipt_date ) AS MONTH ,
SUM( CASE WHEN fm.fee_name = 'University Fees' THEN f.fee_amount END ) AS A
FROM fee_type_masters fm
INNER JOIN student_fee_collections f ON fm.id = f.fee_type
GROUP BY MONTH( f.receipt_date )
and my tables are like
CREATE TABLE `fee_type_masters` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`fee_name` varchar(255) DEFAULT NULL,
`fee_type` varchar(255) DEFAULT NULL,
`year` varchar(255) DEFAULT NULL,
`student_type` int(11) DEFAULT NULL,
`due_date` varchar(255) DEFAULT NULL,
`amount` float DEFAULT NULL,
`accounts_master_id` varchar(255) DEFAULT NULL,
`comments` varchar(255) DEFAULT NULL,
`status` varchar(255) DEFAULT NULL,
`sem` varchar(255) DEFAULT NULL,
`degree_id` int(11) DEFAULT NULL,
`approve_needed` varchar(255) DEFAULT NULL,
`concession_allowed` varchar(255) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`relation_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1
CREATE TABLE `student_fee_collections` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`student_id` int(11) DEFAULT NULL,
`fee_type` int(11) DEFAULT NULL,
`fee_amount` int(11) DEFAULT '0',
`due` int(11) DEFAULT '0',
`received` int(11) DEFAULT '0',
`concession` int(11) DEFAULT '0',
`receipt_no` int(11) DEFAULT NULL,
`receipt_date` date DEFAULT NULL,
`received_by` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`amount` int(11) DEFAULT '0',
`late_fee` int(11) DEFAULT '0',
`pay_mode` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`comments` text COLLATE utf8_unicode_ci,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `student_id` (`fee_type`,`student_id`)
) ENGINE=InnoDB AUTO_INCREMENT=325 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
each is having more than 20000 rows
and my explain plan is like
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE fm ALL PRIMARY NULL NULL NULL 7000 Using temporary; Using filesort
1 SIMPLE f ref student_id student_id 5 emsnew.fm.id 28000 Using where
any one please tell me how to optimize the query or rewrite.

Create Index on fee_type column in student_fee_collections and recheck the output of Explain Query. And update the same in your question.

Create Index on fee_type column in student_fee_colle
and run the following query
SELECT MONTHNAME( f.receipt_date ) AS MONTH ,
SUM( CASE WHEN fm.fee_name = 'University Fees' THEN f.fee_amount END ) AS A
FROM fee_type_masters fm
INNER JOIN student_fee_collections f USE index(fee_type_IDX) ON fm.id = f.fee_type
GROUP BY MONTH( f.receipt_date )

Related

mysql 'slow queries log' return a huge number of rows examined but explain seems ok

The sql query
# Query_time: 16.536276 Lock_time: 0.000159 Rows_sent: 756 Rows_examined: 8392194
SET timestamp=1555422526;
SELECT c.id AS c__id, c.company_id AS c__company_id,
c.ordinary_price AS c__ordinary_price, c.nights AS c__nights,
c.food_type AS c__food_type, c.period AS c__period,
c.period_desc AS c__period_desc, c.extra AS c__extra,
c.coupons_bought AS c__coupons_bought, c.coupon_price AS c__coupon_price,
c.coordinates AS c__coordinates, c.best_price AS c__best_price,
c.from_price AS c__from_price, c.end_datetime AS c__end_datetime,
c.hide_clock AS c__hide_clock, c.hide_discount AS c__hide_discount,
c.booking_hotel_id AS c__booking_hotel_id, c.title AS c__title,
c.option_people AS c__option_people, c.option_room AS c__option_room,
c.option_period AS c__option_period, c.city AS c__city,
c2.id AS c2__id, c2.people AS c2__people, c2.room AS c2__room,
( SELECT c8.url AS c8__url
FROM campaign_images c8
WHERE (c8.campaign_id = c.id
AND c8.photo_type = 'list')
ORDER BY c8.ordering ASC LIMIT 1
) AS c__0
FROM campaign c
LEFT JOIN campaign_options c2 ON c.id = c2.campaign_id
AND (c2.active = 1)
LEFT JOIN city_in_campaign c3 ON c.id = c3.campaign_id
LEFT JOIN city c4 ON c3.city_id = c4.id
LEFT JOIN company c5 ON c.company_id = c5.id
LEFT JOIN campaign_in_category c6 ON c.id = c6.campaign_id
LEFT JOIN campaign_in_group c7 ON c.id = c7.campaign_id
WHERE c.id IN ('13308', '13281', '13265')
AND (c.status IN ('published')
AND c.start_datetime <= NOW()
AND c.end_datetime >= NOW()
AND c5.id = '2111'
AND c.id != '14624'
AND (c7.group_id in (1)
OR c7.group_id is NULL
)
)
ORDER BY c.coupon_expire_datetime ASC;
create table campaign
CREATE TABLE `campaign` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`company_id` int(11) DEFAULT NULL,
`source_id` int(11) DEFAULT NULL,
`secondary_source_id` int(11) DEFAULT NULL,
`source_hotel_id` int(11) DEFAULT NULL,
`booking_hotel_id` int(11) DEFAULT NULL,
`booking_board_id` int(11) DEFAULT NULL,
`booking_rate` varchar(100) DEFAULT NULL,
`ordinary_price` decimal(9,2) NOT NULL,
`best_price` tinyint(1) NOT NULL DEFAULT '0',
`from_price` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(10) DEFAULT 'draft',
`type` varchar(20) DEFAULT 'other',
`deal_status` varchar(20) DEFAULT 'in_progress',
`coupon_price` decimal(9,2) NOT NULL,
`cosmote_discount` decimal(5,2) DEFAULT NULL,
`nights` int(11) NOT NULL DEFAULT '0',
`period` varchar(255) DEFAULT NULL,
`period_desc` varchar(1000) DEFAULT NULL,
`hide_period` tinyint(1) NOT NULL DEFAULT '0',
`food_type` varchar(100) DEFAULT NULL,
`stars` varchar(100) DEFAULT NULL,
`adults` tinyint(1) DEFAULT NULL,
`childs` tinyint(1) DEFAULT NULL,
`extra` varchar(255) DEFAULT NULL,
`best_point` varchar(511) DEFAULT NULL,
`extra_night_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`high_season_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`high_season_desc` varchar(500) DEFAULT NULL,
`high_season_extra_night_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`family_packages_desc` varchar(1000) DEFAULT NULL,
`coordinates` varchar(70) DEFAULT NULL,
`start_datetime` datetime DEFAULT NULL,
`end_datetime` datetime DEFAULT NULL,
`coupon_expire_datetime` datetime DEFAULT NULL,
`active` tinyint(4) NOT NULL DEFAULT '1',
`city` varchar(255) DEFAULT NULL,
`min_coupons` int(11) NOT NULL DEFAULT '0',
`is_global` tinyint(4) NOT NULL DEFAULT '0',
`hide_clock` tinyint(1) NOT NULL DEFAULT '0',
`hide_discount` tinyint(1) NOT NULL DEFAULT '0',
`hide_purchases` tinyint(1) NOT NULL DEFAULT '0',
`booking_enabled` tinyint(1) NOT NULL DEFAULT '0',
`booking_phone` varchar(50) DEFAULT NULL,
`refresh` tinyint(1) NOT NULL DEFAULT '0',
`installments` tinyint(1) NOT NULL DEFAULT '1',
`receipt` enum('0','1') NOT NULL DEFAULT '0',
`newsletters_sent` tinyint(4) NOT NULL DEFAULT '0',
`max_coupons` int(11) NOT NULL DEFAULT '0',
`max_coupons_per_user` int(11) DEFAULT NULL,
`coupons_bought` int(11) unsigned NOT NULL DEFAULT '0',
`fake_orders` int(11) DEFAULT '0',
`title` varchar(255) DEFAULT NULL,
`newsletter_title` varchar(500) DEFAULT NULL,
`linkwise_title` varchar(500) DEFAULT NULL,
`option_title` varchar(255) DEFAULT NULL,
`option_title_en` varchar(255) DEFAULT NULL,
`option_people` varchar(150) DEFAULT NULL,
`option_room` varchar(150) DEFAULT NULL,
`option_period` varchar(150) DEFAULT NULL,
`name` varchar(1200) DEFAULT NULL,
`description` text,
`highlights` text,
`coupon_instructions` text,
`show_in_recent_deals` tinyint(4) NOT NULL DEFAULT '1',
`youtube_video_id` varchar(100) DEFAULT NULL,
`in_side` tinyint(4) NOT NULL DEFAULT '0',
`family` tinyint(1) NOT NULL DEFAULT '0',
`send_newsletter` tinyint(4) NOT NULL DEFAULT '1',
`resend_newsletter` tinyint(4) NOT NULL DEFAULT '0',
`modified_datetime` timestamp NULL DEFAULT NULL,
`created_datetime` datetime NOT NULL,
`ordering` int(11) unsigned DEFAULT '0',
PRIMARY KEY (`id`),
KEY `company_id_idx` (`company_id`),
KEY `user_id_idx` (`user_id`),
KEY `status_indx` (`status`),
KEY `str_dt_indx` (`start_datetime`),
KEY `end_dt_indx` (`end_datetime`),
KEY `side_indx` (`in_side`),
KEY `ord_indx` (`ordering`),
KEY `global_indx` (`is_global`),
KEY `act_indx` (`active`),
KEY `coup_expr_index` (`coupon_expire_datetime`)
) ENGINE=InnoDB AUTO_INCREMENT=14788 DEFAULT CHARSET=utf8
create table campaign_options
CREATE TABLE `campaign_options` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) NOT NULL,
`coupons_bought` int(11) unsigned NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`name_en` varchar(255) DEFAULT NULL,
`people` varchar(100) DEFAULT NULL,
`room` varchar(100) DEFAULT NULL,
`food` varchar(100) DEFAULT NULL,
`period` varchar(100) DEFAULT NULL,
`coupon_price` decimal(9,2) NOT NULL,
`extra_night_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`high_season_price` decimal(9,2) DEFAULT '0.00',
`high_season_extra_night_price` decimal(9,2) NOT NULL DEFAULT '0.00',
`modified_datetime` timestamp NULL DEFAULT NULL,
`created_datetime` datetime NOT NULL,
`main` tinyint(1) NOT NULL DEFAULT '0',
`family` tinyint(1) NOT NULL DEFAULT '0',
`active` tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `campaign_id_idx` (`campaign_id`),
KEY `active_indx` (`active`),
KEY `family_indx` (`family`),
KEY `main_indx` (`main`)
) ENGINE=InnoDB AUTO_INCREMENT=48990 DEFAULT CHARSET=utf8
create table city_in_campaign
CREATE TABLE `city_in_campaign` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) DEFAULT NULL,
`city_id` int(11) DEFAULT NULL,
`ordering` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `campaign_id_idx` (`campaign_id`),
KEY `city_id_idx` (`city_id`),
KEY `order_indx` (`ordering`)
) ENGINE=InnoDB AUTO_INCREMENT=227176 DEFAULT CHARSET=utf8
create table city
CREATE TABLE `city` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`country_id` int(11) DEFAULT NULL,
`name` varchar(100) DEFAULT NULL,
`is_active` tinyint(3) unsigned DEFAULT NULL,
`modified_datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `country_id_idx` (`country_id`),
KEY `is_active_indx` (`is_active`)
) ENGINE=InnoDB AUTO_INCREMENT=254 DEFAULT CHARSET=utf8
create table company
CREATE TABLE `company` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`ref_id` int(11) DEFAULT NULL,
`name` varchar(100) DEFAULT NULL,
`description` text,
`logo` varchar(255) DEFAULT NULL,
`phone_number` varchar(100) DEFAULT NULL,
`address` varchar(200) DEFAULT NULL,
`coordinates` varchar(70) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`website` varchar(255) DEFAULT NULL,
`skype_name` varchar(50) DEFAULT NULL,
`icq_number` varchar(255) DEFAULT NULL,
`payment_information` text,
`extra1` text,
`extra2` text,
`extra3` text,
`video` varchar(500) DEFAULT NULL,
`checked` tinyint(1) NOT NULL DEFAULT '0',
`ordering` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `checked_indx` (`checked`),
KEY `ordering_indx` (`ordering`)
) ENGINE=InnoDB AUTO_INCREMENT=2519 DEFAULT CHARSET=utf8
create table campaign_in_category
CREATE TABLE `campaign_in_category` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) NOT NULL,
`category_id` int(11) DEFAULT NULL,
`ordering` int(11) NOT NULL DEFAULT '0',
`created_datetime` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `campaign_id_idx` (`campaign_id`),
KEY `category_id_idx` (`category_id`),
KEY `order_indx` (`ordering`)
) ENGINE=InnoDB AUTO_INCREMENT=457080 DEFAULT CHARSET=utf8
create table campaign_in_group
CREATE TABLE `campaign_in_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) DEFAULT NULL,
`group_id` int(11) DEFAULT NULL,
`created_datetime` datetime DEFAULT NULL,
`modified_datetime` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `camp_group_indx` (`campaign_id`,`group_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1175 DEFAULT CHARSET=utf8
campaign total rows: 12,657
campaign_options total rows: 43,714
city_in_campaign total rows: 15,162
city total rows: 215
company total rows: 1,756
campaign_in_category total rows: 38,817
campaign_in_group total rows: 395
explain of the query
which ones have index
it looks you need composite index because file sorting.
usage:
CREATE INDEX index_name
ON table_name(c2,c3,c4);
You are getting above result because some time o/p of explain gives different result as response of query of prod.
For optimization of query you can't have a fix answer. it varies from case to case. As for this situation I think you need to perform performance testing of this query. You can do this by inserting some records in all referenced table and then checking it's performance using explain.
LEFT JOIN campaign_in_category c6 ON c.id = c6.campaign_id
seems to be totally useless. But the Optimizer may not realize it. Remove it and any other dead code.

How to optimize a select query with multiple left joins in a large database

my query is
select cp_emp_personal_detail.id
,cp_emp_personal_detail.emp_code
,cp_emp_personal_detail.emp_name
,cp_department.department
,GROUP_CONCAT(TIME(devicelogs_3_2018.LogDate) ORDER BY devicelogs_3_2018.LogDate) present
from cp_emp_personal_detail
left join cp_emp_official_detail on cp_emp_official_detail.emp_id = cp_emp_personal_detail.id
left join devicelogs_3_2018 on devicelogs_3_2018.DeviceId = cp_emp_personal_detail.org_id and cp_emp_personal_detail.id AND date(devicelogs_3_2018.LogDate) = CURRENT_DATE()
left join cp_department on cp_emp_official_detail.department = cp_department.id
where cp_emp_personal_detail.org_id = 1
group by cp_emp_personal_detail.id
and database design is:
CREATE TABLE `cp_emp_personal_detail` (
`id` int(11) NOT NULL,
`org_id` int(11) NOT NULL,
`emp_code` varchar(100) DEFAULT NULL,
`emp_name` varchar(100) NOT NULL,
`emp_guardian_name` varchar(100) DEFAULT NULL,
`emp_dob` date NOT NULL,
`emp_email` varchar(100) DEFAULT NULL,
`emp_password` varchar(100) NOT NULL,
`emp_phone` bigint(15) DEFAULT NULL,
`emp_mobile` bigint(15) NOT NULL,
`emp_emergency_no` int(11) DEFAULT NULL,
`emp_address1` longtext NOT NULL,
`emp_address2` longtext,
`emp_city` int(11) NOT NULL,
`emp_pan` varchar(30) NOT NULL,
`emp_country` int(11) NOT NULL,
`emp_state` int(11) NOT NULL,
`emp_aadhar` varchar(30) DEFAULT NULL,
`emp_tax_status` varchar(100) NOT NULL,
`emp_pic` varchar(255) DEFAULT NULL,
`emp_gender` varchar(50) NOT NULL,
`emp_status` varchar(100) NOT NULL DEFAULT 'activate',
`crm_status` varchar(11) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1
PARTITION BY LIST (org_id)
(
PARTITION P1 VALUES IN (1) ENGINE=InnoDB,
PARTITION P2 VALUES IN (2) ENGINE=InnoDB
);
CREATE TABLE `devicelogs_3_2018` (
`DeviceLogId` bigint(20) NOT NULL,
`DownloadDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`DeviceId` bigint(20) NOT NULL,
`UserId` varchar(50) NOT NULL,
`LogDate` timestamp NOT NULL DEFAULT '1970-12-31 18:30:01',
`Direction` varchar(255) DEFAULT NULL,
`AttDirection` varchar(255) DEFAULT NULL,
`C1` varchar(255) DEFAULT NULL,
`C2` varchar(255) DEFAULT NULL,
`C3` varchar(255) DEFAULT NULL,
`C4` varchar(255) DEFAULT NULL,
`C5` varchar(255) DEFAULT NULL,
`C6` varchar(255) DEFAULT NULL,
`C7` varchar(255) DEFAULT NULL,
`WorkCode` varchar(255) DEFAULT NULL,
`hrapp_syncstatus` tinyint(4) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `cp_department` (
`id` int(11) NOT NULL,
`org_id` int(11) NOT NULL,
`department` varchar(20) NOT NULL,
`depart_abb` varchar(10) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1
PARTITION BY LIST (org_id)
(
PARTITION P1 VALUES IN (1) ENGINE=InnoDB,
PARTITION P2 VALUES IN (2) ENGINE=InnoDB
);
CREATE TABLE `cp_emp_official_detail` (
`id` int(11) NOT NULL,
`emp_id` int(11) NOT NULL,
`org_id` int(11) NOT NULL,
`joining_date` date DEFAULT NULL,
`confirmation_periode` int(11) DEFAULT NULL,
`job_type` varchar(100) DEFAULT NULL,
`payment_mode` varchar(100) DEFAULT NULL,
`department` int(11) DEFAULT NULL,
`acc_no` int(11) DEFAULT NULL,
`designation` int(11) DEFAULT NULL,
`ess_status` int(11) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_updated_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1
PARTITION BY LIST (org_id)
(
PARTITION P1 VALUES IN (1) ENGINE=InnoDB,
PARTITION P2 VALUES IN (2) ENGINE=InnoDB
);
can someone explain me how to optimize th query currently it is taking 3 to 4 min to execute with more than 8k records

mysql query to fetch records from multiple tables and join

I have 5 tables named: schools, candidates, candidate_subjects, subjects, lgas
Each school belong to a lga, each candidate belong to a school, each candidate registers subjects
Below are the table structures:
CREATE TABLE `subjects` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
`code` varchar(10) DEFAULT NULL,
`exam_type_id` int(11) DEFAULT NULL,
`status` int(11) DEFAULT NULL,
`type` varchar(3) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=60 DEFAULT CHARSET=latin1;
CREATE TABLE `candidates` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`exam_no` varchar(20) DEFAULT NULL,
`surname` varchar(100) DEFAULT NULL,
`other_names` varchar(150) DEFAULT NULL,
`school_id` int(11) DEFAULT NULL,
`exam_type_id` int(11) DEFAULT NULL,
`dob` varchar(12) DEFAULT NULL,
`sex` varchar(6) DEFAULT NULL,
`no_of_subjects` int(2) DEFAULT NULL,
`nationality` varchar(20) DEFAULT NULL,
`state` varchar(20) DEFAULT NULL,
`lga` varchar(20) DEFAULT NULL,
`exam_year` varchar(4) DEFAULT NULL,
`date_created` varchar(255) DEFAULT NULL,
`date_modified` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`registration_completed` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28034 DEFAULT CHARSET=latin1;
CREATE TABLE `candidate_subjects` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`candidate_id` int(11) DEFAULT NULL,
`exam_type_id` int(10) DEFAULT NULL,
`subject_id` int(10) DEFAULT NULL,
`ca_score` int(11) DEFAULT NULL,
`exam_score` int(6) DEFAULT NULL,
`score_grade` varchar(10) DEFAULT NULL,
`date_created` varchar(10) DEFAULT NULL,
`date_modified` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=327740 DEFAULT CHARSET=latin1;
CREATE TABLE `schools` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`passcode` varchar(15) DEFAULT NULL,
`code` varchar(10) DEFAULT NULL,
`name` varchar(200) DEFAULT NULL,
`lga` int(11) DEFAULT NULL,
`address` varchar(250) DEFAULT NULL,
`phone` varchar(50) DEFAULT NULL,
`exam_year` varchar(10) DEFAULT NULL,
`eo_name` varchar(100) DEFAULT NULL,
`eo_phone` varchar(50) DEFAULT NULL,
`eo_email` varchar(100) DEFAULT NULL,
`date_created` varchar(10) DEFAULT NULL,
`date_modified` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`profile_created` int(1) DEFAULT NULL,
`entries_purchased` int(11) DEFAULT NULL,
`entries_used` int(11) DEFAULT NULL,
`entries_remaining` int(11) DEFAULT NULL,
`scratchcard_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=652 DEFAULT CHARSET=latin1;
CREATE TABLE `lgas` (
`lga_id` int(11) NOT NULL AUTO_INCREMENT,
`lga_name` varchar(250) NOT NULL,
`state_id` varchar(20) NOT NULL,
PRIMARY KEY (`lga_id`)
) ENGINE=InnoDB AUTO_INCREMENT=786 DEFAULT CHARSET=latin1;
I want to generate a report for each lga like this:
S/No| Name of School |Eng|Mth|B.sc|....Total registered
That is name of school from the selected lga, total number of students from that school that registered for Eng, Mth, B.sc ... Total number of students that registered those subjects from that school
SELECT
b.name as school_name,
sum(case when e.name = 'Eng' then 1 else 0 end) as english_students,
sum(case when e.name = 'Mth' then 1 else 0 end) as math_students,
sum(case when e.name = 'B.sc' then 1 else 0 end) as whatever_this_is_students
FROM lgas a
LEFT JOIN schools b ON a.lga_id = b.lga
LEFT JOIN candidates c on b.id = c.school_id
LEFT JOIN candidate_subjects d on c.id = d.candidate_id
LEFT JOIN subjects e on d.subject_id = e.id
WHERE a.lda_id = 'selected_id'
GROUP by school_name;

MySQL Slow ORDER BY when done on JOIN value?

I have this query:
SELECT
c.*,
cv.views
FROM
content AS c
JOIN
content_views AS cv ON cv.content = c.record_num
WHERE
c.enabled = 1
ORDER BY
cv.views
Quite simple, but it's really slow... Is there a way to make it faster ?
This is my EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE c ref enabled_2,enabled enabled 4 const 23947 Using temporary; Using filesort
1 SIMPLE cv eq_ref PRIMARY PRIMARY 4 c.record_num 1
EDIT 2016-02-24
Please note that usually, I use a LIMIT so the number of records returned in the EXPLAIN isn't entirely accurate, however for the sake of simplicity and because the performance doesn't change with the LIMIT or without it, I have removed it.
As requested in the comments, this is the result of my SHOW CREATE TABLE. As you can see, one of my table is MyISAM while the other is InnoDB.
CREATE TABLE `content` (
`title` varchar(255) NOT NULL DEFAULT '',
`filename` varchar(255) NOT NULL DEFAULT '',
`filename_2` varchar(255) NOT NULL,
`filename_3` varchar(255) NOT NULL,
`orig_filename` varchar(255) NOT NULL,
`trailer_filename` varchar(255) NOT NULL,
`thumbnail` varchar(255) NOT NULL DEFAULT '',
`embed` text NOT NULL,
`description` text NOT NULL,
`paysite` int(11) NOT NULL DEFAULT '0',
`keywords` varchar(255) NOT NULL,
`model` varchar(255) NOT NULL DEFAULT '',
`scheduled_date` date NOT NULL DEFAULT '0000-00-00',
`date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`encoded_date` datetime NOT NULL,
`rating` int(5) NOT NULL DEFAULT '0',
`length` int(11) NOT NULL DEFAULT '0',
`submitter` int(11) NOT NULL DEFAULT '0',
`ip` varchar(15) NOT NULL,
`approved` int(11) NOT NULL DEFAULT '0',
`hotlinked` varchar(1024) NOT NULL,
`plug_url` varchar(255) NOT NULL,
`enabled` int(11) NOT NULL DEFAULT '0',
`main_thumb` int(11) NOT NULL DEFAULT '3',
`xml` varchar(32) NOT NULL,
`photos` int(11) NOT NULL DEFAULT '0',
`mobile` varchar(255) NOT NULL,
`modeltmp` varchar(255) NOT NULL,
`movie_width` int(11) NOT NULL,
`movie_height` int(11) NOT NULL,
`token` varchar(255) DEFAULT NULL,
`source_thumb_url` varchar(255) NOT NULL,
`related` varchar(1024) NOT NULL,
`force_related` varchar(255) NOT NULL,
`record_num` int(11) NOT NULL AUTO_INCREMENT,
`webvtt_src` text NOT NULL,
`category_thumb` int(11) NOT NULL,
`related_date` date NOT NULL,
`publish_ready` tinyint(1) NOT NULL,
PRIMARY KEY (`record_num`),
KEY `encoded_date` (`encoded_date`,`photos`,`enabled`),
KEY `filename` (`filename`),
KEY `scheduled_date` (`scheduled_date`),
KEY `enabled_2` (`enabled`,`length`,`photos`),
KEY `enabled` (`enabled`,`encoded_date`,`photos`),
KEY `rating` (`rating`,`enabled`,`photos`),
KEY `token` (`token`),
KEY `submitter` (`submitter`),
FULLTEXT KEY `keywords` (`keywords`,`title`),
FULLTEXT KEY `title` (`title`),
FULLTEXT KEY `description` (`description`),
FULLTEXT KEY `keywords_2` (`keywords`)
) ENGINE=MyISAM AUTO_INCREMENT=124207 DEFAULT CHARSET=latin1
CREATE TABLE `content_views` (
`views` int(11) NOT NULL,
`content` int(11) NOT NULL,
PRIMARY KEY (`content`),
KEY `views` (`views`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
For this query:
SELECT c.*, cv.views
FROM content c JOIN
content_views cv
ON cv.content = c.record_num
WHERE c.enabled = 1
ORDER BY cv.views;
The best indexes are probably content(enabled, record_num) and content_views(content, views). I am guessing that the performance even with these indexes will be similar to what you have now.

MySQL find a row when the sum of points become bigger than number

I have such sql query
SELECT *,(p.datetime-u.createtime)/86400 as result
FROM tbl_user_points p
Inner join tbl_users u ON u.id=p.user_id
GROUP BY p.user_id
HAVING SUM(p.points) > 100
order by SUM(p.points)
i need to find the datetime( the row in table tbl_user_points), when each users reached.
For more information Here the schemata of table
tbl_user_points
CREATE TABLE `tbl_user_points` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`action` int(10) unsigned NOT NULL,
`description` varchar(255) DEFAULT '',
`points` int(10) NOT NULL DEFAULT '0',
`datetime` int(10) unsigned NOT NULL,
`club_id` int(10) unsigned DEFAULT NULL,
`event_id` int(10) unsigned DEFAULT NULL,
`location_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='Achieved users points for any actions.';
Here the schemata of table
tbl_users
CREATE TABLE `tbl_users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`email` varchar(128) NOT NULL,
`activkey` varchar(128) NOT NULL DEFAULT '',
`createtime` int(11) NOT NULL,
`lastvisit` int(11) NOT NULL,
`superuser` int(1) NOT NULL DEFAULT '0',
`status` int(1) NOT NULL DEFAULT '1',
`first_name` varchar(128) DEFAULT NULL,
`last_name` varchar(128) DEFAULT NULL,
`gender` varchar(6) DEFAULT NULL,
`locale` varchar(45) DEFAULT NULL,
`service` varchar(45) NOT NULL,
`service_id` varchar(255) DEFAULT NULL,
`location` varchar(128) DEFAULT NULL,
`state` int(3) DEFAULT NULL,
`photo` varchar(255) DEFAULT NULL,
`city` varchar(125) DEFAULT NULL,
`about_me` varchar(255) DEFAULT NULL,
`user_code` varchar(10) DEFAULT NULL,
`loyalty_level` varchar(45) DEFAULT 'basic' COMMENT 'Level of loyalty for current user',
`updatetime` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `user_code_UNIQUE` (`user_code`),
KEY `status` (`status`),
KEY `superuser` (`superuser`)
) ENGINE=InnoDB AUTO_INCREMENT=1033 DEFAULT CHARSET=utf8;
sample input
tbl_user_points
id | user_id|action|description|points| datetime
2246 1 1 First visit 5 1383331212
2254 1 2 Second visit 15 1383354853
2255 1 3 Winner 25 1383360231
2256 2 1 First visit 5 1383331202
2257 2 2 Second visit 15 1383354553
2258 2 3 Winner 25 1383360211
tbl_user simple,for example
id=1,createtime=1313000000
id=2,createtime=1313000001
for HAVING SUM(p.points) > 15
output should be
user_id datetime
1 1383354853
2 1383354553
Use CASE syntax. Check this link:
http://dev.mysql.com/doc/refman/5.0/en/case.html.
You can achieve it by using statements like this:
Select X, case when y>100 then desired_row when y<100 then desired_row end as 'desired_row' from your_table where column=your_condition order by 1
Here you're conditioning the select clause by as many cases or conditions you requiere.