How can I select unanswered questions? - mysql

I have a table like this:
CREATE TABLE `qanda` (
`id` int(11) UNSIGNED NOT NULL,
`subject` varchar(150) COLLATE utf8_unicode_ci NOT NULL,
`body` text COLLATE utf8_unicode_ci NOT NULL,
`body_html` text COLLATE utf8_unicode_ci NOT NULL,
`related` int(11) UNSIGNED DEFAULT NULL,
`type` tinyint(1) NOT NULL,
`amount` decimal(11,0) DEFAULT NULL,
`closed` tinyint(1) UNSIGNED DEFAULT NULL,
`CloserId` varchar(500) COLLATE utf8_unicode_ci NOT NULL,
`AcceptedAnswer` tinyint(1) DEFAULT NULL,
`aadate` int(11) UNSIGNED DEFAULT NULL,
`category` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`keywords` varchar(150) COLLATE utf8_unicode_ci NOT NULL,
`visibility` tinyint(1) NOT NULL,
`author_id` int(11) UNSIGNED DEFAULT NULL,
`editor_id` int(11) UNSIGNED DEFAULT NULL,
`date_time` int(11) UNSIGNED NOT NULL,
`edited_at` int(11) UNSIGNED DEFAULT NULL,
`activated_at` int(11) UNSIGNED DEFAULT NULL,
`activated_story` enum('سوال شده','ویرایش شده','جواب داده شده','') COLLATE utf8_unicode_ci NOT NULL,
`activator_id` int(11) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
This table stores both questions and answers. Here is my current query which provides a list of all questions and sort them based on the vote:
SELECT *, (SELECT COALESCE(sum(vv.value),0)
FROM votes vv
WHERE qanda.id = vv.post_id) AS total_votes
FROM qanda
WHERE type = 0 -- "type=0" means questions
ORDER BY total_votes DESC
LIMIT :j,11;
Now I need one more condition on the WHERE clause to exclude questions that have answer(s). I guess I need a self-join. But I don't know how can I write a join on the where clause. Is there any suggestion?

Use NOT IN to exclude IDs that were answered:
SELECT *, (SELECT COALESCE(sum(vv.value),0)
FROM votes vv
WHERE qanda.id = vv.post_id) AS total_votes
FROM qanda
WHERE type = 0
AND id NOT IN (SELECT related FROM quanda WHERE type <> 0)
ORDER BY total_votes DESC
LIMIT :j,11;

With a SELF JOIN, you try to match a question with any answer. If you don't find a match you will get NULL so you will get the questions without answers.
SELECT questions.*
FROM qanda questions
LEFT JOIN qanda answers
ON question.id = answers.related
WHERE questions.type = 0
AND answers.id IS NULL

Related

MySQL COUNT(Joining table) is taking too long to fetch the data inside large tables

Description:
We have two tables as below:
table_1 ("question" main table)
table_2 ("question_attempted" joining table)
Cases:
In "table_2" we have a column that has a column "is_correct" (holds 1,0) for right or wrong answers.
In "table_1" we have 1 m records and in "table_2" we have 10m records
We want to sort our listing data by below columns/values:
Total number of times questions were attempted
Total number of times questions were answered correctly
The percentages questions were answered correctly (based on above two values)
Issue:
As soon as we join the table_1 and table_2 to get the count of total_questions_attempted, total_questiones_give_correct_answer, perntage_corrected_given_answers. The query starts taking around 8-10 minutes to run. Table structures are given below. Thanks in advance.
Table structures:
CREATE TABLE IF NOT EXISTS `question` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`category` bigint(20) NOT NULL DEFAULT 0,
`parent` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
`name` text COLLATE utf8mb4_unicode_ci NOT NULL,
`questiontext` text COLLATE utf8mb4_unicode_ci NOT NULL,
`questiontextformat` tinyint(4) NOT NULL DEFAULT 0,
`generalfeedback` text COLLATE utf8mb4_unicode_ci NOT NULL,
`generalfeedbackformat` tinyint(4) NOT NULL DEFAULT 0,
`defaultmark` decimal(12,7) NOT NULL DEFAULT 1.0000000,
`penalty` decimal(12,7) NOT NULL DEFAULT 0.3333333,
`qtype` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '''1''',
`length` bigint(20) UNSIGNED NOT NULL DEFAULT 1,
`stamp` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`version` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`hidden` tinyint(3) UNSIGNED NOT NULL DEFAULT 0,
`timecreated` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
`timemodified` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
`createdby` bigint(20) UNSIGNED DEFAULT NULL,
`modifiedby` bigint(20) UNSIGNED DEFAULT NULL,
`type_data_id` bigint(20) NOT NULL,
`img_id` bigint(20) DEFAULT NULL,
`qimg_gallary_text` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`qrimg_gallary_text` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`qimg_gallary_ids` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`qrimg_gallary_ids` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`case_id` bigint(20) NOT NULL DEFAULT 0,
`ques_type_id` bigint(20) DEFAULT NULL,
`year` bigint(20) DEFAULT NULL,
`spec` bigint(20) DEFAULT NULL,
`sub_speciality_id` int(11) DEFAULT NULL,
`sub_sub_speciality_id` int(11) DEFAULT NULL,
`spec_level` bigint(20) DEFAULT 1,
`is_deleted` int(11) NOT NULL DEFAULT 0,
`sequence` int(11) NOT NULL DEFAULT 0,
`sort_order` bigint(20) NOT NULL DEFAULT 0 COMMENT 'Question order in list',
`idnumber` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`addendum` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`text_for_search` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'this is for the text based searching, this will store the text of the question without html tags',
`text_for_search_ans` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `type_data_id` (`type_data_id`),
UNIQUE KEY `mdl_ques_catidn_uix` (`category`,`idnumber`),
KEY `mdl_ques_cat_ix` (`category`),
KEY `mdl_ques_par_ix` (`parent`),
KEY `mdl_ques_cre_ix` (`createdby`),
KEY `mdl_ques_mod_ix` (`modifiedby`),
KEY `id` (`id`),
KEY `mq_spec_ix` (`spec`),
KEY `sort_order` (`sort_order`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='The questions themselves';
CREATE TABLE IF NOT EXISTS `question_attempted` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`questionusageid` bigint(20) UNSIGNED NOT NULL,
`slot` bigint(20) UNSIGNED NOT NULL,
`behaviour` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`questionid` bigint(20) UNSIGNED NOT NULL,
`variant` bigint(20) UNSIGNED NOT NULL DEFAULT 1,
`maxmark` decimal(12,7) NOT NULL,
`minfraction` decimal(12,7) NOT NULL,
`flagged` tinyint(3) UNSIGNED NOT NULL DEFAULT 2,
`questionsummary` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`rightanswer` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`responsesummary` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`timemodified` bigint(20) UNSIGNED NOT NULL,
`maxfraction` decimal(12,7) DEFAULT 1.0000000,
`in_remind_state` int(11) NOT NULL DEFAULT 0,
`is_correct` tinyint(1) DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `mdl_quesatte_queslo_uix` (`questionusageid`,`slot`),
KEY `mdl_quesatte_que_ix` (`questionid`),
KEY `mdl_quesatte_que2_ix` (`questionusageid`),
KEY `mdl_quesatte_beh_ix` (`behaviour`),
KEY `questionid` (`questionid`),
KEY `is_correct` (`is_correct`)
) ENGINE=InnoDB AUTO_INCREMENT=151176 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Each row here corresponds to an attempt at one question, as ';
I tried with the below query:
SELECT mq.id, mq.name, COUNT(is_correct)
FROM mdl_question_attempts as mqa
LEFT JOIN mdl_question mq on mq.id = mqa.questionid where mq.id IS NOT NULL and mq.is_deleted = '0'
GROUP by mqa.questionid
ORDER by mq.sort_order desc, mq.id DESC
LIMIT 50
https://i.stack.imgur.com/mHK6W.png
The correct query is
SELECT mq.id, mq.name, COUNT(mqa.questionid)
FROM mdl_question mq
LEFT JOIN mdl_question_attempts mqa ON mq.id = mqa.questionid AND mqa.is_correct
WHERE NOT mq.is_deleted
GROUP by mq.id
ORDER by mq.sort_order DESC, mq.id DESC
LIMIT 50;
Now let's see, how fast this can get. There is just one criteria on the question table (WHERE NOT mq.is_deleted). We can probably assume that very many if not most questions are not deleted, so using an index here makes no sense on first glance; reading the full table seems quicker.
Then we outer join the answers on the question ID and the is_correct flag. This means we should at least have an index on the ID, better even on the ID and the flag:
CREATE INDEX idx1 ON mdl_question_attempts (questionid, is_correct);
Now we must order all rows by the question's sort_order and ID to get the first 50 rows. It would be great to have an index that is already sorted, so we could just take the first 50 entries from there. But then, we are only looking at rows matching NOT mq.is_deleted, so the index must include that flag:
CREATE INDEX idx2 ON mdl_question (is_deleted, sort_order DESC, id DESC);
We could even include the name, so all data is available from the index and the table must not be read anymore (covering index).
CREATE INDEX idx2 ON mdl_question (is_deleted, sort_order DESC, id DESC, name);
It is still up to the DBMS to use these indexes or not. We are just providing them to give the DBMS the option. With this query it depends on how well MySQL's optimizer works. Does it see that it can just read the 50 first entries from the question index and then use the answer index for the simple counting?
add index in your table
CREATE INDEX index_name ON table_name (column_name);
references : https://www.w3schools.com/sql/sql_create_index.asp

Filtering results in MySQL in join result

I am beginner programmer. I have small problem with my MySQL Queries.
This is my MySQL data: https://pastebin.com/69PcBSVH
I have this tables:
CREATE TABLE `dishes` (
`id` bigint(20) UNSIGNED NOT NULL,
`company_id` bigint(20) UNSIGNED NOT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`description` longtext COLLATE utf8mb4_unicode_ci,
`enable` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `dish_values` (
`id` bigint(20) UNSIGNED NOT NULL,
`dishes_id` bigint(20) UNSIGNED NOT NULL,
`food_ingredient_id` bigint(20) UNSIGNED NOT NULL,
`company_id` bigint(20) UNSIGNED NOT NULL,
`quantity` decimal(9,2) NOT NULL DEFAULT '0.00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `food_ingredients` (
`id` bigint(20) UNSIGNED NOT NULL,
`company_id` bigint(20) UNSIGNED NOT NULL,
`name` varchar(120) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`garbage` decimal(9,2) NOT NULL DEFAULT '0.00',
`energy_value` decimal(9,2) NOT NULL DEFAULT '0.00',
`protein` decimal(9,2) NOT NULL DEFAULT '0.00',
`fat` decimal(9,2) NOT NULL DEFAULT '0.00',
`available_carbohydrates` decimal(9,2) NOT NULL DEFAULT '0.00',
`roughage` decimal(9,2) NOT NULL DEFAULT '0.00',
`description` longtext COLLATE utf8mb4_unicode_ci,
`url_address` varchar(160) COLLATE utf8mb4_unicode_ci NOT NULL,
`allergen` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`allergen1` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`allergen2` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`allergen3` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`available_in_demo` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`enable` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
My base is a base of dishes and ingredients needed to prepare a dish.
I need to display all dishes that are not allergens (food_ingredients.allergen = 0).
Table dishes = given dishes
Table dish_values = ingredients that are assigned to a given dish
Food_ingredients table = ingredients of the dish.
Dishes that are allergens have a value of 1 in the allergen column and those that are not allergens 0.
I make query to show my dish (without allergens):
SELECT
dishes.id, dishes.company_id, dishes.name, dishes.description, dishes.enable
FROM `dishes` join dish_values on dish_values.dishes_id = dishes.id
join food_ingredients on food_ingredients.id = dish_values.food_ingredient_id
WHERE food_ingredients.allergen = 0
GROUP BY dishes.id
But it's not working correct.
As a result, I have both dishes that contain allergens and those that do not have them.
How can I repair it?
I would use not’exists with a correlated subquery: this avoids the need for aggregation, which is generally not good for performance on large datasets:
select d.*
from dishes d
where not exists (
select 1
from dish_values v
inner join food_ingredients i on i.id = v.food_ingredient_id
where
v.dishes_id = d.id
and i.allergen = 1
)
For performance, you want the following index: food_ingredients(allergen, id).
Side note: you should change the data type of allergen from char(1) to tinyint(1) since it only contains 0/1 values.
As allergen is a char column, you need quotes around the 0. Alternatively, you can change the column to an int.
Remove the WHERE clause and add the condition to the HAVING clause:
SELECT d.id, d.company_id, d.name, d.description, d.enable
FROM dishes d
INNER JOIN dish_values v ON v.dishes_id = d.id
INNER JOIN food_ingredients i ON i.id = v.food_ingredient_id
GROUP BY d.id, d.company_id, d.name, d.description, d.enable
HAVING SUM(i.allergen) = 0
The condition SUM(i.allergen) = 0 makes sure that all matching rows from the table food_ingredients have i.allergen = 0.

MySQL query optimization improvement

Hello all I have a MySQL query that fetches data from more than on tables. Here is my query
SELECT
user_id as id,
user_name as name,
user_phone as phone,
user_email as email,
user_address1 as address1,
user_address2 as address2,
user_city as city,
user_state as state,
user_country as country,
user_available as available,
user_location as location,
user_latitude as latitude,
user_longitude as longitude,
user_description as description,
user_company as company,
user_gender as gender,
(SELECT MIN(service_price) FROM service WHERE service.user_id = a.user_id) as price,
(SELECT service_recomanded FROM service WHERE service.user_id = a.user_id ORDER BY service.service_price ASC LIMIT 1) as recomandad,
verified_email,
verified_facebook,
verified_phone,
verified_twitter,
(SELECT providerphoto_name FROM providerphoto WHERE providerphoto.user_id = a.user_id ORDER BY providerphoto_order ASC LIMIT 1 ) as photo,
(SELECT ROUND( AVG(review_rate),2) FROM review WHERE review.user_id = a.user_id ) AS rate,
(SELECT service_ICOC FROM service WHERE service.user_id = a.user_id ORDER BY service_price ASC LIMIT 1) as type
FROM
user a
WHERE a.user_type = 'provider'
AND a.user_active=1
AND a.user_deleted=0
It gets data from user table, service table, review table and providerphoto table. It works too but the execution time is very slow. I guess to make it a single query and avoid the inner five queries may run it fast. Any help?
Table structures.
--
-- Table structure for table `providerphoto`
--
CREATE TABLE IF NOT EXISTS `providerphoto` (
`providerphoto_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`providerphoto_file` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`providerphoto_name` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`providerphoto_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`providerphoto_order` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`providerphoto_id`),
KEY `user_id` (`user_id`),
KEY `providerphoto` (`user_id`,`providerphoto_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=487 ;
-- --------------------------------------------------------
--
-- Table structure for table `review`
--
CREATE TABLE IF NOT EXISTS `review` (
`review_id` int(11) NOT NULL AUTO_INCREMENT,
`review_title` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_id` int(11) NOT NULL,
`review_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`review_content` text COLLATE utf8_unicode_ci NOT NULL,
`review_user_id` int(11) NOT NULL,
`review_rate` int(10) NOT NULL DEFAULT '1',
`review_tip` int(11) NOT NULL DEFAULT '0',
`service_booked` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`review_id`),
KEY `user_id` (`user_id`),
KEY `review_date` (`review_date`),
KEY `review_user_id` (`review_user_id`),
KEY `review_rate` (`review_rate`),
KEY `review_tip` (`review_tip`),
KEY `service_booked` (`service_booked`),
KEY `review` (`user_id`,`review_rate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=97 ;
-- --------------------------------------------------------
--
-- Table structure for table `service`
--
CREATE TABLE IF NOT EXISTS `service` (
`service_id` int(11) NOT NULL AUTO_INCREMENT,
`service_name` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`service_created_by` int(11) NOT NULL DEFAULT '0',
`service_ICOC` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`service_price` int(11) NOT NULL,
`service_date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`service_date_expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`service_time` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`service_rate` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`service_type` int(10) NOT NULL DEFAULT '1' COMMENT '1-in call, 2-out call, 3-in&out call',
`service_recomanded` int(2) NOT NULL DEFAULT '0',
`service_genre` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`service_message` text COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`service_id`),
KEY `user_id` (`user_id`),
KEY `service_ICOC` (`service_ICOC`(255)),
KEY `service` (`user_id`,`service_price`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=854 ;
-- --------------------------------------------------------
--
-- Table structure for table `user`
--
CREATE TABLE IF NOT EXISTS `user` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_password` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_email` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_phone` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_address1` text COLLATE utf8_unicode_ci,
`user_address2` text COLLATE utf8_unicode_ci NOT NULL,
`user_city` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_state` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_country` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_company` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_birthday` date DEFAULT NULL,
`user_register_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`user_type` enum('provider','client') COLLATE utf8_unicode_ci DEFAULT NULL,
`user_description` text COLLATE utf8_unicode_ci NOT NULL,
`user_available` int(10) NOT NULL DEFAULT '1',
`verified_email` tinyint(1) NOT NULL DEFAULT '0',
`verified_facebook` tinyint(1) NOT NULL DEFAULT '0',
`verified_phone` tinyint(1) NOT NULL DEFAULT '0',
`verified_twitter` tinyint(1) NOT NULL DEFAULT '0',
`user_facebook_friends` int(11) NOT NULL DEFAULT '0',
`user_twitter_friends` int(11) NOT NULL DEFAULT '0',
`user_longitude` decimal(10,5) NOT NULL DEFAULT '0.00000',
`user_latitude` decimal(10,5) NOT NULL DEFAULT '0.00000',
`user_deleted` tinyint(4) NOT NULL DEFAULT '0',
`user_gender` int(11) NOT NULL DEFAULT '0',
`user_facebook_token` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`user_active` tinyint(4) NOT NULL DEFAULT '1',
`user_location` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`user_push_notification_token` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`user_timezone_diff` int(11) NOT NULL DEFAULT '0',
`balanced_uri` text COLLATE utf8_unicode_ci NOT NULL,
`user_reset_passwd_token` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`is_test_user` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`),
KEY `deleted_idx` (`user_deleted`),
KEY `email_idx` (`user_email`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=426 ;
You can probably just add indexes to speed up the query. Try adding the following indexes:
service(user_id, service_price)
providerphoto(user_id, providerphoto_order)
review(user_id, review_rate)
Something like this. This will return all the values for the users as I did not use the ORDER and LIMIT in the query. This is just for the approach.
SELECT
a.user_id as id,
user_name as name,
user_phone as phone,
user_email as email,
user_address1 as address1,
user_address2 as address2,
user_city as city,
user_state as state,
user_country as country,
user_available as available,
user_location as location,
user_latitude as latitude,
user_longitude as longitude,
user_description as description,
user_company as company,
user_gender as gender,
MIN(s.service_price) as price,
s.service_recomanded as recomandad,
verified_email,
verified_facebook,
verified_phone,
verified_twitter,
pp.providerphoto_name as photo,
ROUND( AVG(r.review_rate),2) as rate,
s.service_ICOC as type
FROM
user a LEFT JOIN service s on s.user_id = a.user_id LEFT JOIN providerphoto pp on pp.user_id = a.user_id LEFT JOIN review r on r.user_id = a.user_id
WHERE a.user_type = 'provider'
AND a.user_active=1
AND a.user_deleted=0;
First thing I would do is index user.user_type, user.user_deleted and user.user_active to let the optimizer quickly start with a smaller set of user records to have to deal with.
Do you mean to allow service.user_id to be NULL? That seems like a mistake.
Also you may want to throw indexes on any columns where you're doing an ORDER BY.
The best way to find out what is slow in this query is to do a EXPLAIN QUERY and analyze what it tells you. We can help you with that as well.

query taking too much time with irritated performance [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
My query is taking very long time around 1hr
it was impacting on DB performance.
even for Explain plan also it was taking very long time.
please rewrite the query for optimal performance.
Query:
SELECT Count(*)
FROM (SELECT paid.keyword_id,
paid.keyword_name,
stat.orgentrances,
keyword.rank1,
keyword.rank_check,
Sum(paid.clicks) AS sumclick,
Sum(paid.clicks * paid.avg_position) AS
sumclickavgpos,
Sum(paid.itemrevenue) AS sumitem,
Sum(paid.cost) AS sumcost,
Sum(paid.transactions) AS sumtrans,
Sum(paid.impressions) AS
sumimpress,
IF(Sum(paid.impressions) = 0, 0, Sum(
paid.impressions * paid.avg_position) / Sum
(paid.impressions)) AS
sumimpressavgrank,
con.item_revenue,
con.transactions,
keyword.monthly_search_volume
FROM `t_keyword_paid_analytics_google_ib` paid
LEFT JOIN (SELECT outer_t.keyword_id,
Sum(outer_t.item_revenue) AS item_revenue,
Sum(outer_t.transactions) AS transactions
FROM t_keyword_conversion_ga_ib outer_t
WHERE outer_t.own_domain_id = 720
AND outer_t.traffic_date >= '2012-12-01'
AND outer_t.traffic_date <= '2012-12-31'
GROUP BY outer_t.keyword_id) con
ON paid.keyword_id = con.keyword_id
LEFT JOIN (SELECT outer_t.keyword_id,
Sum(outer_t.entrances) AS orgEntrances
FROM t_keyword_stat_ga_ib outer_t
WHERE outer_t.own_domain_id = 720
AND outer_t.traffic_date >= '2012-12-01'
AND outer_t.traffic_date <= '2012-12-31'
AND ( outer_t.medium = 'organic'
OR outer_t.medium IS NULL )
GROUP BY outer_t.keyword_id) stat
ON paid.keyword_id = stat.keyword_id
LEFT JOIN `t_managed_keyword_ib` keyword
ON keyword.id = paid.keyword_id
WHERE paid.own_domain_id = 720
AND paid.traffic_date >= '2012-12-01'
AND paid.traffic_date <= '2012-12-31'
AND ( paid.channel IS NULL
OR paid.channel = 'Google' )
GROUP BY paid.keyword_id
HAVING paid.keyword_id IS NOT NULL) tempt;
(outer_t.medium = 'organic' or outer_t.medium is null ) after outer_t.own_domain_id = 720 and (paid.channel is null or paid.channel = 'Google')
after paid.own_domain_id = 720
Tables Structure:
mysql> show create table t_keyword_paid_analytics_google_ib\G
*************************** 1. row ***************************
Table: t_keyword_paid_analytics_google_ib
Create Table: CREATE TABLE `t_keyword_paid_analytics_google_ib` (
`keyword_name` varchar(255) DEFAULT NULL,
`id` int(11) NOT NULL,
`keyword_id` int(11) NOT NULL,
`target_url_id` int(11) DEFAULT NULL,
`own_domain_id` int(11) NOT NULL,
`log_date` date NOT NULL,
`traffic_date` date NOT NULL,
`impressions` int(11) DEFAULT NULL,
`clicks` int(11) DEFAULT NULL,
`entrances` int(11) DEFAULT NULL,
`match_type` int(11) DEFAULT NULL COMMENT '1: Phrase, 2: Exact, 3:Broad 4: etc',
`ad_group_name` varchar(200) DEFAULT NULL,
`ad_distribution_network` varchar(500) CHARACTER SET latin1 DEFAULT NULL,
`match_query` varchar(500) CHARACTER SET latin1 DEFAULT NULL,
`cost` decimal(10,2) DEFAULT NULL,
`cpm` decimal(10,2) DEFAULT NULL,
`ctr` decimal(10,2) DEFAULT NULL COMMENT 'percent',
`cpc` decimal(10,2) DEFAULT NULL,
`campaign` varchar(200) CHARACTER SET latin1 DEFAULT NULL,
`keyword_status` tinyint(4) DEFAULT NULL COMMENT '1: Active,2: Approved, 3: Disapproved, 4: Paused , 5:Pending, 6: Failed, 7:etc',
`ad_group_status` tinyint(4) DEFAULT NULL COMMENT '1:ELIGIBLE; 2=PAUSED;3=LOW_SEARCH_VOLUME;4 =LOW_QUALITY_SCORE; 5=DISAPPROVED; 6=AD_GROUP_PAUSED; 7=etc',
`max_cpc` decimal(10,2) DEFAULT NULL,
`quality_score` tinyint(4) DEFAULT NULL,
`channel` varchar(100) DEFAULT NULL,
`first_page_cpc` decimal(10,2) DEFAULT NULL,
`avg_position` decimal(10,2) DEFAULT NULL,
`itemRevenue` decimal(10,2) DEFAULT NULL,
`goal1value` decimal(10,2) DEFAULT NULL,
`goal2value` decimal(10,2) DEFAULT NULL,
`goal3value` decimal(10,2) DEFAULT NULL,
`goal4value` decimal(10,2) DEFAULT NULL,
`transactions` int(10) DEFAULT NULL,
`goal1completions` int(10) DEFAULT NULL,
`goal2completions` int(10) DEFAULT NULL,
`goal3completions` int(10) DEFAULT NULL,
`goal4completions` int(10) DEFAULT NULL
) ENGINE=BRIGHTHOUSE DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> show create table t_keyword_conversion_ga_ib\G
*************************** 1. row ***************************
Table: t_keyword_conversion_ga_ib
Create Table: CREATE TABLE `t_keyword_conversion_ga_ib` (
`keyword_name` varchar(255) COLLATE latin1_bin DEFAULT NULL,
`id` int(11) NOT NULL,
`own_domain_id` int(11) DEFAULT NULL,
`keyword_id` int(11) DEFAULT NULL,
`traffic_date` date DEFAULT NULL,
`targeturl_id` int(11) DEFAULT NULL,
`entrance` int(11) DEFAULT NULL,
`transactions` int(11) DEFAULT NULL,
`item_revenue` decimal(9,2) DEFAULT NULL,
`goal1completions` int(11) DEFAULT NULL,
`goal2completions` int(11) DEFAULT NULL,
`goal3completions` int(11) DEFAULT NULL,
`goal4completions` int(11) DEFAULT NULL,
`goal5completions` int(11) DEFAULT NULL,
`goal6completions` int(11) DEFAULT NULL,
`goal7completions` int(11) DEFAULT NULL,
`goal8completions` int(11) DEFAULT NULL,
`goal9completions` int(11) DEFAULT NULL,
`goal10completions` int(11) DEFAULT NULL,
`goal1Value` decimal(9,2) DEFAULT NULL,
`goal2Value` decimal(9,2) DEFAULT NULL,
`goal3Value` decimal(9,2) DEFAULT NULL,
`goal4Value` decimal(9,2) DEFAULT NULL,
`goal5Value` decimal(9,2) DEFAULT NULL,
`goal6Value` decimal(9,2) DEFAULT NULL,
`goal7Value` decimal(9,2) DEFAULT NULL,
`goal8Value` decimal(9,2) DEFAULT NULL,
`goal9Value` decimal(9,2) DEFAULT NULL,
`goal10Value` decimal(9,2) DEFAULT NULL,
`medium` varchar(255) COLLATE latin1_bin DEFAULT NULL,
`source` varchar(255) COLLATE latin1_bin DEFAULT NULL
) ENGINE=BRIGHTHOUSE DEFAULT CHARSET=latin1 COLLATE=latin1_bin
1 row in set (0.00 sec)
please help me here.
You don't indicate any indexes. You will need them to improve performance.
OK, I don't understand the part after the semi-colon, so I'll ignore that.
Your whole query does a count(*) of a sub select, but you are doing a bunch of aggregation in the sub-query (calling SUM) which is work the database doesn't have to do, so eliminate that.
You do aggregation in further sub-queries, so cut that out.
In your main sub-select, where you are just doing a count(*), you select fields that are not in your group by, which is work on the database that is not affecting the count, so get rid of that.
That gives us something like...
select count(*)
from (select paid.keyword_id
from `t_keyword_paid_analytics_google_ib` paid
left join
(select outer_t.keyword_id
from t_keyword_conversion_ga_ib outer_t
where ...
group by outer_t.keyword_id ) con
on paid.keyword_id = con.keyword_id
left join
(select outer_t.keyword_id
from t_keyword_stat_ga_ib outer_t
where ...
group by outer_t.keyword_id) stat on paid.keyword_id = stat.keyword_id
left join `t_managed_keyword_ib` keyword on keyword.id = paid.keyword_id
where ...
group by paid.keyword_id
having paid.keyword_id is not null
) tempt;
Also, counts may be faster than selects and you seem to be looking for the keyword_id and counting them in the end. If you can count as you go that would be better than selecting. I'm not sure if you can apply that to this query, but keep it in mind.
You have to add some index to your tables,
ALTER TABLE table_name ADD UNIQUE INDEX cate_id(field_name);
here is the documentation
In your case I would add index to:
paid.keyword_id
con.keyword_id
stat.keyword_id
keyword.id
paid.keyword_id
because you are making join on those fields

sql statement mysql notcorrect

SELECT SUBSTRING(m.own,3,4) as c , (select amphur.AMPHUR_NAME where c = SUBSTRING(m.own,3,4) ),
COUNT(* ) AS cnt
FROM MEMBER AS m
GROUP BY SUBSTRING(m.own,3,4)
order by cnt desc
sql statement mysql
what wrong with code below when i fill
(select amphur.AMPHUR_NAME where c = SUBSTRING(m.own,3,4) )
it error
CREATE TABLE IF NOT EXISTS `member` (
`idmember` int(11) NOT NULL AUTO_INCREMENT,
`own` varchar(255) DEFAULT NULL,
`Sname` varchar(255) DEFAULT NULL,
`Ssurname` varchar(255) DEFAULT NULL,
`Sex` enum('¿','¿') NOT NULL,
`Hno` varchar(255) DEFAULT NULL,
`Moo` varchar(255) DEFAULT NULL,
`tambol` varchar(200) NOT NULL,
`dateofbirth` date DEFAULT NULL,
`migratedate` date DEFAULT NULL,
`status` enum('5','4','3','2','1') DEFAULT '5',
`Unit` int(4) DEFAULT NULL,
`staff1` int(11) DEFAULT NULL,
`staff2` int(11) DEFAULT NULL,
`fathercode` varchar(30) NOT NULL,
`mathercode` varchar(30) NOT NULL,
PRIMARY KEY (`idmember`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=8994 ;
CREATE TABLE IF NOT EXISTS `amphur` (
`AMPHUR_ID` int(5) NOT NULL AUTO_INCREMENT,
`AMPHUR_CODE` varchar(4) COLLATE utf8_unicode_ci NOT NULL,
`AMPHUR_NAME` varchar(150) COLLATE utf8_unicode_ci NOT NULL,
`GEO_ID` int(5) NOT NULL DEFAULT '0',
`PROVINCE_ID` int(5) NOT NULL DEFAULT '0',
`province_name` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`AMPHUR_ID`),
KEY `province_name` (`province_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=999 ;
Your subquery is missing a From clause:
SELECT SUBSTRING(m.own,3,4) as c
, (select amphur.AMPHUR_NAME
From amphur
Where ??? = SUBSTRING(m.own,3,4) )
, COUNT(* ) AS cnt
FROM MEMBER AS m
However, how does the amphur table relate to the member table?
You cannot use aliases in the same level.
Even if you could, you are filtering on non-correlated columns in your subquery: the subquery would just return the record from amphur if there is one record, or an error if there are more.
Could you please provide some sample data and the desired recordset?
there is no "FROM" clause in your select Amphur.amphur_name