简体   繁体   中英

Transform mysql Subquery to Left Join

suppose I have the following table:

    id  parent
    1   1
    2   1
    3   1
    4   1
    5   2
    6   5
    7   5

And I want to execute the following query:

SELECT id_table.parent,id_table.count_id 
FROM 
    (SELECT count(id) AS count_id,parent FROM item group by parent) AS id_table
     WHERE id_table.count_id = 
         (SELECT max(count_id) AS max_count_id FROM
                      ( SELECT count(id) AS count_id,parent
                            FROM item group by parent ) AS id_table2 )

to get the following result:

parent  count_id    
1       4

I try to transform the query to optimize performance:

SELECT id_table.parent,id_table.count_id FROM
      (SELECT count(id) AS count_id,parent FROM item GROUP BY parent)
              AS id_table    
LEFT JOIN

      (SELECT count(id) AS count_id,parent FROM item GROUP BY parent )
              AS id_table2    
ON id_table.parent=id_table2.parent AND id_table.count_id<id_table2.count_id

WHERE id_table2.parent IS NULL

BUT got the following result instead, which I don't want:

parent  count_id    
1       4
2       1   
5       2

This is my reference

Could anyone tell me where I did wrong? regards

Your second query does not work as you wish because it simply does not match any records in the join. Look:

You are declaring a join between a certain query and itself, according to the following condition:

ON id_table.parent=id_table2.parent AND id_table.count_id<id_table2.count_id

This means: select all the records from the first query (because it is a LEFT join), and every record from the second query which has the same parent and a count lower than the first query. ¡!

As you can see, this is absurd: Since the auto-joined query returns these records:

count_id parent
4        1
2        2
2        5

... the parent column is a de-facto PK. So. the pair (4,1) has no matching pairs (x,1) with x<4. (Idem the rest of the pairs.)

That was your mistake: The example from MySQL is not appliable here, because in the shop table, surely there are more than one record with the same value of article , which is not your case of ( parent has unique values in the auto-joined query).

The only query formula based on joins that comes to my mind is like this:

SELECT count_id, parent
FROM (SELECT count(id) AS count_id,parent FROM item GROUP BY parent) query1
INNER JOIN (SELECT MAX(query2.count_id) as max_id FROM (SELECT count(id) AS count_id,parent FROM item GROUP BY parent) query2) queryMax ON query1.count_id=queryMax.max_id;

... but I doubt that such a complexity it will improve the performance of your first approach.

Based on your output which you wanted to get i got a simpler solution. Maybe i didn't understand your question, but i'll give a shot.

Why to use your query (kinda long and messy) :

SELECT id_table.parent,id_table.count_id 
FROM 
(SELECT count(id) AS count_id,parent FROM item group by parent) AS id_table
 WHERE id_table.count_id = 
     (SELECT max(count_id) AS max_count_id FROM
                  ( SELECT count(id) AS count_id,parent
                        FROM item group by parent ) AS id_table2 )

I acomplished the same result with much more simpler query.

SELECT parent, count(id) as count_id FROM items GROUP BY 1 ORDER BY 2 DESC LIMIT 1

To get the following result.

parent  count_id    
1       4

Can you check this

SELECT parent,count(*) AS parent_count FROM parent group by parent
 ORDER BY parent_count DESC LIMIT 1

Hope this helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM