Search code examples
mysqlsqlsql-order-bysqlperformance

Slow SQL Query with Sub Query with Order By


Here's the query:

SELECT product.catalog_product_id AS catalog_id, listing.id AS listing_id, 
    product.size AS size, 0 AS amount, 
    listing.list_price AS price, 
    listing.created_at AS created_date 
FROM product
INNER JOIN listing ON listing.product_id = product.id 
WHERE product.catalog_product_id = XXXX
    AND listing.id = (
        SELECT l.id
        FROM listing l
        INNER JOIN product i ON l.product_id = i.id
        WHERE i.size = product.size AND i.catalog_product_id = XXXX
        ORDER BY l.list_price ASC, l.created_at ASC
        LIMIT 1
    ) 

Sub Query is this get listing ID for lowest price. Sub Query is slowing down with Order by. I have already created indexes and it still takes 5-6 seconds.

Table Structure:

catalog: This is master products catalog table

Catalog
-------
id
sku
name
description

products : Stores product variant(size options)

Products
--------
id
catalog_id
size 

listing table:: stores product listing, One Product size option can have multiple product listings with different prices.

listing
---------
id
product_id
list_price
created_at

Output: http://prntscr.com/kqh7fg

It shows lowest price for each listing and size.


Solution

  • I was able to sort out this.

    SELECT product.catalog_product_id AS catalog_id, listing.id AS listing_id, 
    product.size AS size,
    listing.list_price AS price, 
    listing.created_at AS created_date
    FROM product
    INNER JOIN listing ON listing.product_id = product.id
    AND product.catalog_product_id = XXXX 
    AND listing.id IN 
    (
    SELECT MIN(l.id)
    FROM listing l
    INNER JOIN product i ON l.product_id = i.id
    WHERE i.catalog_product_id = XXXX 
    AND list_price = (
    SELECT MIN(list_price)
    FROM listing l
    INNER JOIN product it ON l.product_id = it.id
    WHERE it.catalog_product_id = XXXX AND it.size = i.size
    )
    GROUP BY i.size
    )
    

    Instead of using:

    ORDER BY l.list_price ASC, l.created_at ASC  LIMIT 1
    

    I have used Min(Price) and Group By Size to get min price listing.

    Query Performance improved from 5 sec to .5 seconds

    Thanks!