I am a beginner in MySQL and trying to create a join query in MySQL.
My first SQL query is as below which displays the 2 columns votes and post
SELECT votes, post
FROM `wp_votes` where votes!=''
GROUP BY votes,post asc LIMIT 0 , 30
**Second table is where the posts are **
SELECT *
FROM `wp_posts`
LIMIT 0 , 30
What i wanna do is create a join so that it display all records from wp_posts table WHERE wp_post.ID=wp_votes.post, Also have to check if wp_votes.votes!=''
I tried the following but i am stuck on it
SELECT * FROM wp_posts join wp_votes ON wp_posts.ID =wp_votes.post
Table Structure below
CREATE TABLE IF NOT EXISTS `wp_posts` (
`ID` bigint(20) unsigned NOT NULL auto_increment,
`post_author` bigint(20) unsigned NOT NULL default '0',
`post_date` datetime NOT NULL default '0000-00-00 00:00:00',
`post_date_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
`post_content` longtext NOT NULL,
`post_title` text NOT NULL,
`post_excerpt` text NOT NULL,
`post_status` varchar(20) NOT NULL default 'publish',
`comment_status` varchar(20) NOT NULL default 'open',
`ping_status` varchar(20) NOT NULL default 'open',
`post_password` varchar(20) NOT NULL default '',
`post_name` varchar(200) NOT NULL default '',
`to_ping` text NOT NULL,
`pinged` text NOT NULL,
`post_modified` datetime NOT NULL default '0000-00-00 00:00:00',
`post_modified_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
`post_content_filtered` longtext NOT NULL,
`post_parent` bigint(20) unsigned NOT NULL default '0',
`guid` varchar(255) NOT NULL default '',
`menu_order` int(11) NOT NULL default '0',
`post_type` varchar(20) NOT NULL default 'post',
`post_mime_type` varchar(100) NOT NULL default '',
`comment_count` bigint(20) NOT NULL default '0',
PRIMARY KEY (`ID`),
KEY `post_name` (`post_name`),
KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
KEY `post_parent` (`post_parent`),
KEY `post_author` (`post_author`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4570 ;
--
-- Table structure for table `wp_votes`
--
CREATE TABLE IF NOT EXISTS `wp_votes` (
`ID` int(11) NOT NULL auto_increment,
`post` int(11) NOT NULL,
`votes` text NOT NULL,
`guests` text NOT NULL,
`usersinks` text NOT NULL,
`guestsinks` text NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1052 ;
SELECT a.votes, a.post,
b.*
FROM wp_votes a
INNER JOIN wp_Post b
ON a.post = b.ID
WHERE a.votes <> ''
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Related
I have such a tables offers and offer_operating_systems related by offer_id. I made two queris and from my understanding they should return same result, but they don't
Query 1:
select
count(*)
from
`offers`
where
(
select count(*)
from `offer_operating_systems`
where
`offer_operating_systems`.`offer_id` = `offers`.`id`
and
`operating_system` = 'android'
) = 1
order by `id` asc
Query 2:
select
count(*)
from offer_operating_systems
where
operating_system = 'android'
order by `id` asc
Can someone explain to me why the results are not the same? Thanks!
EDITED
operating_systemcolumn is unique so each offer can have only one record with adnroid
Table structures
CREATE TABLE `offers` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`type` int(11) NOT NULL DEFAULT '0',
`url` text COLLATE utf8_unicode_ci,
`status` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'pending',
`api_created_at` timestamp NULL DEFAULT NULL,
`api_updated_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `offers_status_index` (`status`)
) ENGINE=InnoDB AUTO_INCREMENT=423 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `offer_operating_systems` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`offer_id` int(10) unsigned NOT NULL,
`operating_system` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `offer_operating_systems_offer_id_operating_system_unique` (`offer_id`,`operating_system`),
KEY `offer_operating_systems_offer_id_foreign` (`offer_id`),
CONSTRAINT `offer_operating_systems_offer_id_foreign` FOREIGN KEY (`offer_id`) REFERENCES `offers` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=728 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
I have following mysql query which is taking long time(40s) to load the results.
SELECT SQL_CALC_FOUND_ROWS blog_posts.ID FROM blog_posts
LEFT JOIN blog_term_relationships AS tt0 ON (blog_posts.ID = tt0.object_id)
LEFT JOIN blog_term_relationships AS tt1 ON (blog_posts.ID = tt1.object_id)
LEFT JOIN blog_term_relationships AS tt2 ON (blog_posts.ID = tt2.object_id)
LEFT JOIN blog_term_relationships AS tt3 ON (blog_posts.ID = tt3.object_id)
WHERE 1=1
AND ( ( tt0.term_taxonomy_id IN (141,177) AND tt1.term_taxonomy_id IN (2389,2390) )
OR ( tt2.term_taxonomy_id IN (167,1169,1715) AND tt3.term_taxonomy_id IN (2519,2520) ) )
AND blog_posts.post_type = 'post' AND (blog_posts.post_status = 'publish')
GROUP BY blog_posts.ID ORDER BY blog_posts.post_date ASC LIMIT 0, 20
Is there any way to optimize this query.
Edit:
This is related to wordpress and this query was automatically create from the wp_query.
Table structures as bellow,
blog_posts table:
CREATE TABLE `blog_posts` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_author` bigint(20) unsigned NOT NULL DEFAULT '0',
`post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_date_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_content` longtext NOT NULL,
`post_title` text NOT NULL,
`post_excerpt` text NOT NULL,
`post_status` varchar(20) NOT NULL DEFAULT 'publish',
`comment_status` varchar(20) NOT NULL DEFAULT 'open',
`ping_status` varchar(20) NOT NULL DEFAULT 'open',
`post_password` varchar(255) NOT NULL DEFAULT '',
`post_name` varchar(200) NOT NULL DEFAULT '',
`to_ping` text NOT NULL,
`pinged` text NOT NULL,
`post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_modified_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`post_content_filtered` longtext NOT NULL,
`post_parent` bigint(20) unsigned NOT NULL DEFAULT '0',
`guid` varchar(255) NOT NULL DEFAULT '',
`menu_order` int(11) NOT NULL DEFAULT '0',
`post_type` varchar(20) NOT NULL DEFAULT 'post',
`post_mime_type` varchar(100) NOT NULL DEFAULT '',
`comment_count` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
KEY `post_parent` (`post_parent`),
KEY `post_author` (`post_author`),
KEY `post_name` (`post_name`(191))
) ENGINE=MyISAM AUTO_INCREMENT=125636 DEFAULT CHARSET=utf8
blog_term_relationships table:
CREATE TABLE `blog_term_relationships` (
`object_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`term_taxonomy_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`term_order` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`object_id`,`term_taxonomy_id`),
KEY `term_taxonomy_id` (`term_taxonomy_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
EXPLAIN QUERY:
enter image description here
Reformulate
SELECT SQL_CALC_FOUND_ROWS blog_posts.ID
FROM (
(
SELECT object_id
FROM blog_term_relationships AS tt0
JOIN blog_term_relationships AS tt1 USING(object_id)
WHERE tt0.term_taxonomy_id IN (141,177)
AND tt1.term_taxonomy_id IN (2389,2390)
)
UNION DISTINCT
(
SELECT object_id
FROM blog_term_relationships AS tt2
JOIN blog_term_relationships AS tt3 USING(object_id)
WHERE tt2.term_taxonomy_id IN (167,1169,1715)
AND tt3.term_taxonomy_id IN (2519,2520) )
) AS tt
JOIN blog_posts ON blog_posts.ID = tt.object_id
WHERE blog_posts.post_type = 'post'
AND blog_posts.post_status = 'publish'
ORDER BY blog_posts.post_date ASC
LIMIT 0, 20
This gets rid of the GROUP BY and does several other things to speed up the query.
Prefix index
`post_name` varchar(200) NOT NULL DEFAULT '',
KEY `post_name` (`post_name`(191))
) ENGINE=MyISAM AUTO_INCREMENT=125636 DEFAULT CHARSET=utf8
Make up your mind -- 191 is for version 5.6 with utf8mb4 (which you have not specified); 191 is so close to 200, you may as well make it VARCHAR(191). Getting rid of the prefix index is likely to speed up some of your queries.
InnoDB
Don't use MyISAM, move to InnoDB. That is for performance, robustness, etc. That will coincidentally fix an inefficiency in KEY term_taxonomy_id).
SQL_CALC_FOUND_ROWS
SQL_CALC_FOUND_ROWS is costly. It's purpose is passe.
I’m trying to create a query in mySQL to select data from pre-existing tables on a database (Moodle to be specific). I realise that the scheme isn’t great, but this has come from the Moodle database with the ‘ratings’ plugin installed.
The current data structure looks like this:
mdl_ranking_points
CREATE TABLE `mdl_ranking_points` (
`id` bigint(10) NOT NULL AUTO_INCREMENT,
`userid` bigint(10) NOT NULL,
`courseid` bigint(10) NOT NULL,
`points` decimal(10,1) NOT NULL,
`timecreated` bigint(10) NOT NULL,
`timemodified` bigint(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='Points of users'
mdl_ranking_logs
CREATE TABLE `mdl_ranking_logs` (
`id` bigint(10) NOT NULL AUTO_INCREMENT,
`rankingid` bigint(10) NOT NULL,
`courseid` bigint(10) NOT NULL,
`course_modules_completion` bigint(10) NOT NULL,
`points` decimal(10,1) NOT NULL,
`timecreated` bigint(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8 COMMENT='Points of users'
mdl_user
CREATE TABLE `mdl_user` (
`id` bigint(10) NOT NULL AUTO_INCREMENT,
`auth` varchar(20) NOT NULL DEFAULT 'manual',
`confirmed` tinyint(1) NOT NULL DEFAULT '0',
`username` varchar(100) NOT NULL DEFAULT '',
`password` varchar(255) NOT NULL DEFAULT '',
`idnumber` varchar(255) NOT NULL DEFAULT '',
`firstname` varchar(100) NOT NULL DEFAULT '',
`lastname` varchar(100) NOT NULL DEFAULT '',
`email` varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `mdl_user_mneuse_uix` (`mnethostid`,`username`),
KEY `mdl_user_fir_ix` (`firstname`),
KEY `mdl_user_las_ix` (`lastname`),
KEY `mdl_user_idn_ix` (`idnumber`),
) ENGINE=InnoDB AUTO_INCREMENT=1045 DEFAULT CHARSET=utf8 COMMENT='One record for each person'
mdl_course
CREATE TABLE `mdl_course` (
`id` bigint(10) NOT NULL AUTO_INCREMENT,
`category` bigint(10) NOT NULL DEFAULT '0',
`sortorder` bigint(10) NOT NULL DEFAULT '0',
`fullname` varchar(254) NOT NULL DEFAULT '',
`shortname` varchar(255) NOT NULL DEFAULT '',
`idnumber` varchar(100) NOT NULL DEFAULT '',
`summary` longtext,
`summaryformat` tinyint(2) NOT NULL DEFAULT '0',
`format` varchar(21) NOT NULL DEFAULT 'topics',
`showgrades` tinyint(2) NOT NULL DEFAULT '1',
`newsitems` mediumint(5) NOT NULL DEFAULT '1',
`startdate` bigint(10) NOT NULL DEFAULT '0',
`enddate` bigint(10) NOT NULL DEFAULT '0',
`marker` bigint(10) NOT NULL DEFAULT '0',
`maxbytes` bigint(10) NOT NULL DEFAULT '0',
`legacyfiles` smallint(4) NOT NULL DEFAULT '0',
`showreports` smallint(4) NOT NULL DEFAULT '0',
`visible` tinyint(1) NOT NULL DEFAULT '1',
`visibleold` tinyint(1) NOT NULL DEFAULT '1',
`groupmode` smallint(4) NOT NULL DEFAULT '0',
`groupmodeforce` smallint(4) NOT NULL DEFAULT '0',
`defaultgroupingid` bigint(10) NOT NULL DEFAULT '0',
`lang` varchar(30) NOT NULL DEFAULT '',
`theme` varchar(50) NOT NULL DEFAULT '',
`timecreated` bigint(10) NOT NULL DEFAULT '0',
`timemodified` bigint(10) NOT NULL DEFAULT '0',
`requested` tinyint(1) NOT NULL DEFAULT '0',
`enablecompletion` tinyint(1) NOT NULL DEFAULT '0',
`completionnotify` tinyint(1) NOT NULL DEFAULT '0',
`cacherev` bigint(10) NOT NULL DEFAULT '0',
`calendartype` varchar(30) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `mdl_cour_cat_ix` (`category`),
KEY `mdl_cour_idn_ix` (`idnumber`),
KEY `mdl_cour_sho_ix` (`shortname`),
KEY `mdl_cour_sor_ix` (`sortorder`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='Central course table';
I need to return a query with the following data:
lastname | points | average
I've tried the following query, but this doesnt return what I need (it seems that it only counts user id's that have been awarded points.
SELECT lastname AS academy,
SUM(points) AS score,
COUNT(*) AS users,
(SUM(points)/COUNT(*)) AS norm
FROM mdl_ranking_points r
LEFT JOIN mdl_user ON r.userid = mdl_user.id
LEFT JOIN mdl_course ON r.courseid = mdl_course.id
GROUP BY lastname
ORDER BY norm DESC
Any help would be much appreciated. I may be approaching this completely the wrong way.
I've tried the following query, but this doesnt return what I need (it seems that it only counts user id's that have been awarded points.
This is because of the order in the joins. This will return all users even if they don't have rewarded some points
FROM mdl_user
LEFT OUTER JOIN mdl_ranking_points
LEFT OUTER JOIN mdl_course
Or change your query with a right outer join.
Mentioned below is the query and the tables its is being run on ...
SELECT * FROM
tfl_acquistions a,
tfl_property_attributes b WHERE
a.id = b.property_id AND
attribute_id ='111' AND
a.id ='53a8288c03a6823';
Table tfl_acquistions
CREATE TABLE `tfl_acquistions` (
`id` VARCHAR(32) NOT NULL DEFAULT '',
`address` VARCHAR(100) NOT NULL DEFAULT '',
`city` VARCHAR(50) NOT NULL DEFAULT '',
`state` VARCHAR(10) NOT NULL DEFAULT '',
`zip` VARCHAR(10) NOT NULL DEFAULT '',
`county` VARCHAR(50) NOT NULL DEFAULT '',
`country` VARCHAR(50) NOT NULL DEFAULT '',
`status` ENUM('Y','N') NOT NULL DEFAULT 'Y',
`customer_case` VARCHAR(25) NOT NULL DEFAULT '',
`circle_id` INT(11) NOT NULL DEFAULT '0',
`visneta_id` VARCHAR(45) NOT NULL DEFAULT '',
`add_date` DATE NOT NULL DEFAULT '0000-00-00',
`apt_no` VARCHAR(10) NOT NULL DEFAULT '',
`profile_picture` VARCHAR(256) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
INDEX `address` (`address`),
INDEX `city` (`city`),
INDEX `state` (`state`),
INDEX `zip` (`zip`),
INDEX `status` (`status`),
INDEX `customer_case` (`customer_case`),
INDEX `circle_id` (`circle_id`),
INDEX `visneta_id` (`visneta_id`)
)
Table tfl_property_attributes
CREATE TABLE `tfl_property_attributes` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`property_id` VARCHAR(32) NOT NULL,
`attribute_id` INT(11) NOT NULL DEFAULT '0',
`value` VARCHAR(500) NOT NULL DEFAULT '',
`update_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`update_by` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
INDEX `attribute_id` (`attribute_id`),
INDEX `property_id` (`property_id`),
INDEX `property_id_2` (`property_id`, `attribute_id`)
)
I am on a task to optimized this query and i am new .... any help is appreciated
Try:
SELECT * FROM
tfl_acquistions a JOIN
tfl_property_attributes b ON a.id = b.property_id WHERE
b.property_id = '53a8288c03a6823' AND b.attribute_id = '111';
This way MySQL will be able to use the index property_id_2 (property_id, attribute_id) you have created on the second table. Currently, it can't use any indexes.
Try putting EXPLAIN keyword in front of queries to see how MySQL plans to perform them, you'll see that your previous query does not use any index.
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 )