Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimize query and subquery

Tags:

mysql

Currently i have this:

insert into temp select  * from myTable where (called_phone in
(
    select number1 from
    (
        SELECT *  FROM
        (
            SELECT called_phone as number1, count(*) as conto
            FROM myTable
            GROUP BY called_phone

        ) AS subquery
        union 
        SELECT * FROM
        (
            SELECT calling_phone as number1, count(*) as conto
            FROM myTable
            GROUP BY calling_phone

        ) AS subquery1
    )as subquery3
    GROUP BY number1
    having sum(conto) > 4000
))
or
(calling_phone in 
    (
        select number1 from
        (
            SELECT *  FROM
            (
                SELECT called_phone as number1, count(*) as conto
                FROM myTable
                GROUP BY called_phone

            ) AS subquery
            union 
            SELECT * FROM
            (
                SELECT calling_phone as number1, count(*) as conto
                FROM myTable
                GROUP BY calling_phone

            ) AS subquery1
        )as subquery3
        GROUP BY number1
        having sum(conto) > 4000
    )
);

i have 2 columns (called and calling phone) in which i must check all the occurrency for each number, and store in another table, all the numbers that have the count(*) > 4000 summing the occurence in both the columns. Problem with this query is that i'm doing 2 times the subquery which, by itself scan 2 times MyTable. I was thinking to store the subquery in a temporary table, and then scan it. Is this the best approach? What would you suggest?

EDIT : i'm using MySQL 5.7 with MyISAM as engine

EDIT2 : tried this:

create table test (`number1` VARCHAR(255) not NULL, primary key (`number1`));

insert into test(number1) select number1 from 
    (
        SELECT *  FROM
        (
            SELECT called_phone as number1, count(*) as conto
            FROM myTable
            GROUP BY called_phone

        ) AS subquery
        union 
        SELECT * FROM
        (
            SELECT calling_phone as number1, count(*) as conto
            FROM myTable
            GROUP BY calling_phone

        ) AS subquery1
    )as subquery3
    GROUP BY number1
    having sum(conto) > 4000;



insert into temp select  * from myTable where (called_phone in
(
    select number1 from test
    ))
or
(calling_phone in 
    (
        select number1 from test
));

drop table test;

But this is much more slower (at least on my test data, which is a table of ~14 records)

  • first approach takes 350ms to 380 ms
  • second approach take 800ms to 1.8s

FINAL EDIT : I'm writing the query that is producing the best results, and it comes from the answer of @Daniel E.

insert into temp
SELECT t1.* myTable t1 
INNER JOIN 
 (
   select number1 from
        (
            SELECT *  FROM
            (
                SELECT called_phone as number1, count(*) as conto
                FROM myTable
                GROUP BY called_phone

            ) AS subquery
            union 
            SELECT * FROM
            (
                SELECT calling_phone as number1, count(*) as conto
                FROM myTable
                GROUP BY calling_phone

            ) AS subquery1
        )as subquery3
        GROUP BY number1
        having sum(conto) > 4000
 ) t2 ON (t2.number1 = t1.called_phone
        OR 
         t2.number1 = t1.calling_phone)
  • first approach takes 350ms to 380 ms
  • second approach take 800ms to 1.8s
  • last approach take 315 to 335 ms
like image 971
Daniele Sartori Avatar asked Sep 23 '26 15:09

Daniele Sartori


1 Answers

As you seems to understand the Insert Into I will just rewrite the select, instead of using a IN and a OR, I use 1 inner join :

SELECT t1.* FROM myTable t1 
INNER JOIN 
 (
   select number1 from
        (
            SELECT *  FROM
            (
                SELECT called_phone as number1, count(*) as conto
                FROM myTable
                GROUP BY called_phone

            ) AS subquery
            union 
            SELECT * FROM
            (
                SELECT calling_phone as number1, count(*) as conto
                FROM myTable
                GROUP BY calling_phone

            ) AS subquery1
        )as subquery3
        GROUP BY number1
        having sum(conto) > 4000
 ) t2 ON (t2.number1 = t1.called_phone
        OR 
         t2.number1 = t1.calling_phone)
like image 190
Daniel E. Avatar answered Sep 25 '26 16:09

Daniel E.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!