Stored procedure is so slowly when using count distinct - mysql

When I run the stored procedure for the first time, it is so slow and the process lasts for 1 minute, and then I run it again and it lasts 10 seconds.
Following is my main sql statement, please help me to check out , thank you very much!
example 1
SELECT sql_no_cache view_address.is_facility,count(DISTINCT
view_address.provider_id)as totalCount FROM pv_mview_provider_address view_address WHERE
view_address.network_group_id=5047 AND view_address.carrier_group_id=93 GROUP BY
view_address.is_facility;
explain:
example 2:
SELECT SQL_NO_CACHE is_facility,count(distinct provider_id) FROM (SELECT
view_address.provider_id,view_address.is_facility FROM pv_mview_provider_address
view_address WHERE view_address.network_group_id=5047 AND view_address.carrier_group_id=93
) as p GROUP BY is_facility
explain:
this sql will spend 10 s to load the data.
The table stores 4000,0000 rows.
Thank you very much!

For this query:
select sql_no_cache a.is_facility,
count(distinct a.provider_id) as totalCount
from pv_mview_provider_address a
where a.network_group_id = 5047 and
a.carrier_group_id = 93
group by a.is_facility;
You want an index. The best index is pv_mview_provider_address(network_group_id, carrier_group_id, is_facility). However, if the reference in the from clause is a view and not a table, then you need to figure out what is happening with the view.

Related

DATEDIFF with DATEADD causing slow performance in MySQL query

The query below takes ~2 seconds, which seems really long for such a straightforward join on 2 tables with only ~3000 or so rows.
I strongly suspect the problem is with this line:
but I'm not sure why. Or, perhaps the join condition is screwing things up?
SELECT DISTINCT
, idnum
, DATEDIFF( DATE_ADD(atable.adate, INTERVAL 10 DAY), btable.bdate) as `DIFF`
FROM atable
LEFT JOIN btable
ON atable.idnum = btable.idnum
;
My issue is similar to this, but not the same. Thanks in advance to the great SO community for looking this over.
You can reduce time by creating view of this query and call that view rather than direct query to table.like this
Create view
CREATE VIEW viewname AS SELECT DISTINCT
, idnum
, DATEDIFF( DATE_ADD(atable.adate, INTERVAL 10 DAY), btable.bdate) as `DIFF`
FROM atable
LEFT JOIN btable
ON atable.idnum = btable.idnum
;
Call view
SELECT * FROM viewname
Note: in view approach we create view at once and call that view as many times as we want.

Retrieving rows that have 2 columns matching and 1 different

Below is my table called 'datapoints'. I am trying to retrieve instances where there are different instances of 'sensorValue' for the same 'timeOfReading' and 'sensorNumber'.
For example:
sensorNumber sensorValue timeOfReading
5 5 6
5 5 6
5 6 10 <----same time/sensor diff value!
5 7 10 <----same time/sensor diff value!
Should output: sensorNumber:5, timeOfReading: 10 as a result.
I understand this is a duplicate question, in fact I have one of the links provided below for references - however none of the solutions are working as my query simply never ends.
Below is my SQL code:
SELECT table1.sensorNumber, table1.timeOfReading
FROM datapoints table1
WHERE (SELECT COUNT(*)
FROM datapoints table2
WHERE table1.sensorNumber = table2.sensorNumber
AND table1.timeOfReading = table1.timeOfReading
AND table1.sensorValue != table2.sensorValue) > 1
AND table1.timeOfReading < 20;
Notice I have placed a bound for timeOfReading as low as 20. I also tried setting a bound for both table1 and table 2 as well but the query just runs until timeout without displaying results no matter what I put...
The database contains about 700mb of data, so I do not think I can just run this on the entire DB in a reasonable amount of time, I am wondering if this is the culprit?
If so how could I properly limit my query to run a search efficiently? If not what am doing wrong that this is not working?
Select rows having 2 columns equal value
EDIT:
Error Code: 2013. Lost connection to MySQL server during query 600.000 sec
When I try to run the query again I get this error unless I restart
Error Code: 2006. MySQL server has gone away 0.000 sec
You can use a self-JOIN to match related rows in the same table.
SELECT DISTINCT t1.sensorNumber, t1.timeOfReading
FROM datapoints AS t1
JOIN datapoints AS t2
ON t1.sensorNumber = t2.sensorNumber
AND t1.timeOfReading = t2.timeOfReading
AND t1.sensorValue != t2.sensorValue
WHERE t1.timeOfReading < 20
DEMO
To improve performance, make sure you have a composite index on sensorNumber and timeOfReading:
CREATE INDEX ix_sn_tr on datapoints (sensorNumber, timeOfReading);
I think you have missed a condition. Add a not condition also to retrieve only instances with different values.
SELECT *
FROM new_table a
WHERE EXISTS (SELECT * FROM new_table b
WHERE a.num = b.num
AND a.timeRead = b.timeRead
AND a.value != b.value);
you can try this query
select testTable.* from testTable inner join (
SELECT sensorNumber,timeOfReading
FROM testTable
group by sensorNumber , timeOfReading having Count(distinct sensorValue) > 1) t
on
t.sensorNumber = testTable.sensorNumber and t.timeOfReading = testTable.timeOfReading;
here is sqlFiddle
This query will return the sensorNumber and the timeOfReading where there are different values of sensorValue:
select sensorNumber, timeOfReading
from tablename
group by sensorNumber, timeOfReading
having count(distinct sensorValue)>1
and this will return the actual records:
select t.*
from
tablename t inner join (
select sensorNumber, timeOfReading
from tablename
group by sensorNumber, timeOfReading
having count(distinct sensorValue)>1
) d on t.sensorNumber=d.sensorNumber and t.timeOfReading=d.timeOfReading
I would suggest you to add an index on sensorNumber, timeOfReading
alter table tablename add index idx_sensor_time (sensorNumber, timeOfReading)

SQL: How to decrease the statement execution time?

I'm not an expert in SQL, i have an sql statement :
SELECT * FROM articles WHERE article_id IN
(SELECT distinct(content_id) FROM contents_by_cats WHERE cat_id='$cat')
AND permission='true' AND date <= '$now_date_time' ORDER BY date DESC;
Table contents_by_cats has 11000 rows.
Table articles has 2700 rows.
Variables $now_date_time and $cat are php variables.
This query takes about 10 seconds to return the values (i think because it has nested SELECT statements) , and 10 seconds is a big amount of time.
How can i achieve this in another way ? (Views or JOIN) ?
I think JOIN will help me here but i don't know how to use it properly for the SQL statement that i mentioned.
Thanks in advance.
A JOIN is exactly what you are looking for. Try something like this:
SELECT DISTINCT articles.*
FROM articles
JOIN contents_by_cats ON articles.article_id = contents_by_cats.content_id
WHERE contents_by_cats.cat_id='$cat'
AND articles.permission='true'
AND articles.date <= '$now_date_time'
ORDER BY date DESC;
If your query is still not as fast as you would like then check that you have an index on articles.article_id and contents_by_cats.content_id and contents_by_cats.cat_id. Depending on the data you may want an index on articles.date as well.
Do note that if the $cat and $now_date_time values are coming from a user then you should really be preparing and binding the query rather than just dumping these values into the query.
This is the query we are starting with:
SELECT a.*
FROM articles a
WHERE article_id IN (SELECT distinct(content_id)
FROM contents_by_cats
WHERE cat_id ='$cat'
) AND
permission ='true' AND
date <= '$now_date_time'
ORDER BY date DESC;
Two things will help this query. The first is to rewrite it using exists rather than in and to simplify the subquery:
SELECT a.*
FROM articles a
WHERE EXISTS (SELECT 1
FROM contents_by_cats cbc
WHERE cbc.content_id = a.article_id and cat_id = '$cat'
) AND
permission ='true' AND
date <= '$now_date_time'
ORDER BY date DESC;
Second, you want indexes on both articles and contents_by_cats:
create index idx_articles_3 on articles(permission, date, article_id);
create index idx_contents_by_cats_2 on contents_by_cat(content_id, cat_id);
By the way, instead of $now_date_time, you can just use the now() function in MySQL.

MySQL Function only once with group by

I have the following statement:
SELECT user_id, myMysqlFunction(user_id) FROM users_to_days GROUP BY user_id;
The table stores one row per user and day.
The problem is that MySql calls the Function "myMysqlFunction(user_id)" for every row and groups the rows after that.
My target is to execute the Function just once (for performance reasons).
I tried the following state without success:
SELECT user_id, IF(`date` = min(`date`),myMysqlFunction(user_id),0) FROM users_to_days GROUP BY user_id;
MySql still executes the statement for every row.
If I write a static date (for example '2014-09-01') - it works:
SELECT user_id, IF(`date` = '2014-09-01',myMysqlFunction(user_id),0) FROM users_to_days GROUP BY user_id;
But I don't know the min. date for the user at the time of execution. (its not the same for every user)
you could try a subquery:
SELECT user_id, myMysqlFunction(user_id)
FROM (SELECT user_id
FROM users_to_days
GROUP BY user_id);
Edit: comment got split up, I wanted to say:
I meant: try $date = date('Y-m-d');, that will get the time the user runs it. Put that in min($date), and it should be working.

"where not in (subquery)" very slow for a large table

I want to check whether cust_data_card_id exists or not in table tbl_cust_data , exists in table tbl_cust_dump_data.cust_data_card_id etc.
I wrote the following code
select * from tbl_cust_dump_data
where tbl_cust_dump_data.cust_data_card_id NOT IN
(select cust_data_card_id from tbl_cust_data);
When the query returns more than 18000 rows in tbl_cust_data it doesn't return any result, it only shows the loading for long time, but it is okay smaller sets of data
Try:
SELECT *
FROM tbl_cust_dump_data t1
WHERE NOT EXISTS
(SELECT 0
FROM tbl_cust_data t2
WHERE t2.cust_data_card_id = t1.cust_data_card_id)
With this query you will be able to select rows from tbl_cust_dump_data, if cust_data_card_id doesn't exist in table tbl_cust_data.
I think there was a similar question asked not long ago >> HERE <<. Make sure you have cust_data_card_id indexed and please post the result of
EXPLAIN
select * from tbl_cust_dump_data
where tbl_cust_dump_data.cust_data_card_id NOT IN
(select cust_data_card_id from tbl_cust_data);
So that we can see what can be optimized further.