简体   繁体   中英

MySQL query too slow with JOINS in sub query

I have a database that has 'products' and linked 'products_prices' tables. I'm trying to get the average 'products_prices.price' for all 'products' that match a certain set of criteria. The trick is that I don't need the average price on a particular day, but the aggregate average price for all prices before and including the day the query is grouping by. I'm probably not explaining it very well.

For example, If I had 2 products listed on day one at $100, then row one of the results would show 'totalCount' = 2 and 'totalSum'= $200 for that day. If another price was added on day 2 at $150 then there would now be 2 rows in the results with the 2nd row showing 'totalCount' = 3 and 'totalSum' = $350.

So, the query should be adding the count for all records that match the criteria prior to itself to it's own day.

Does that make sense ?

I have a query that seems to do what I want, but it is terribly slow. I'm pretty sure it is because I am using JOINS in the sub queries.

SELECT pp.created_at,

    (SELECT COUNT(products_prices.id) FROM products_prices 
        INNER JOIN products ON products_prices.product_id = products.id 
        WHERE products_prices.created_at <= pp.created_at
       AND products.make LIKE '%Beneteau%'  
       AND length_feet >= 47
       AND length_feet <= 52
       AND products_prices.marked_as_sold <> 1
       ) AS totalCount,

    (SELECT SUM(products_prices.price) FROM products_prices
       INNER JOIN products ON products_prices.product_id = products.id 
       WHERE products_prices.created_at <= pp.created_at
       AND products.make LIKE '%Beneteau%'
       AND length_feet >= 47
       AND length_feet <= 52
       AND products_prices.marked_as_sold <> 1
       ) AS totalSum

FROM products_prices pp
GROUP BY DAY(pp.created_at) 
ORDER BY created_at

Here are the results this query produces...

created_at  totalCount  totalSum
2018-11-29 00:00:00 0   
2018-11-30 00:00:00 0   
2018-12-01 09:58:14 0   
2018-12-02 04:58:13 0   
2018-12-03 13:15:14 0   
2018-12-04 04:45:12 0   
2018-12-05 01:15:13 0   
2018-12-06 10:15:13 0   
2018-12-07 11:26:41 0   
2018-12-08 00:00:13 2   504000
2018-12-09 01:05:07 2   504000
2018-12-10 01:05:08 2   504000
2018-12-11 00:45:12 2   504000
2018-12-12 01:00:14 2   504000
2018-12-13 01:05:08 2   504000
2018-12-14 01:18:10 2   504000
2018-12-15 00:02:13 2   504000
2018-12-16 00:45:12 2   504000
2018-12-17 00:02:13 2   504000
2018-12-18 01:05:08 2   504000
2018-12-19 00:02:14 11  2535500
2018-12-20 01:05:08 12  2724500
2018-12-21 00:02:14 13  2973500
2018-12-22 00:20:30 13  2973500
2018-12-23 01:15:06 13  2973500
2018-12-24 01:11:09 13  2973500
2018-12-25 01:28:07 13  2973500
2018-12-26 01:25:06 13  2973500
2018-12-27 00:02:09 13  2973500
2018-12-28 00:02:11 13  2973500

There must be a better way to do this. Anyone got any ideas ?

Latest suggestion is this...

SELECT pp.created_at                 ,
COUNT(pp.id) totalCount,
SUM(pp.price) totalSum
FROM products_prices pp
INNER JOIN products 
ON pp.product_id = products.id
GROUP BY DAY(pp.created_at)
HAVING pp.created_at <= pp.created_at
AND  products.make LIKE '%Beneteau%'
AND  length_feet >= 47
AND  length_feet <= 52
AND  pp.marked_as_sold <> 1
ORDER BY created_at;

but it throws "Unknown column 'products.make' in 'having clause'"

Sure - using joins in Subquery is slow

But MySQL supports DESCRIBE

I suspect you need to create some indexes

LIKE is a very slow statement - and quite difficult in indexes

Maybe start with:

SELECT id from products WHERE make LIKE '%Beneteau%';

Store that away then use:

AND product_id IN ([the id's you stored])

Then create some index on product_id, length_feet and marked_as_sold

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