Reputation: 18103
Following from this memory limit problem:
Grabbing 190k rows from MySQL using PHP, blank page? Memory or buffer?
One of the big reasons I reach memory limit today is because of this script:
When I grab reference numbers (which has costs in my application), I would like to grab the price (what it costs).
A reference number price can be found in deal.price, BUT if the reference number/order is a product, I need to find the price in deals_products.price.
Here is my query I start with:
SELECT `refnumbers`.`refno`, `deals`.`price`, `refnumbers`.`order_id` FROM `refnumbers` JOIN `deals` ON (`deals`.`ID` = `refnumbers`.`deal_id`)
Then, to get the price, I always need this piece of code (which I would like help from you, to remove so it all can be found in the query)
foreach($refnumbers as $ref)
{
$isProduct = DB::select('product_id')->from('orders_chosenoptions')
->where('order_id', '=', $ref['order_id'])->execute()->get('product_id', 0);
if($isProduct > 0)
{
$price = DB::select('price')->from('deals_products')
->where('id', '=', $isProduct)
->execute()->get('price');
}else{
$price = $ref['price'];
}
}
(I am using Kohana Query Builder, but the query should be readable to know whats going on)
So you can see that this is very ineffective, 1) i run a query, 2) i go through each row and run two queries to be sure I get the correct price.
And when I go through 190k rows, it basically runs 2x190k single queries as extra
How can i possibly skip this, and have the correct price, right from the first query?
Any answer is appreciated.
Note I cannot modify the db design structure.
UPDATE:
I have tried myself successfully with this query:
SELECT `refnumbers`.`refno`,
CASE WHEN orders_chosenoptions.order_id IS NOT NULL
THEN (SELECT price FROM deals_products WHERE id = orders_chosenoptions.product_id)
ELSE deals.price
END AS price,
`refnumbers`.`order_id`
FROM `refnumbers`
JOIN `deals` ON (`deals`.`ID` = `refnumbers`.`deal_id`)
LEFT JOIN orders_chosenoptions ON (orders_chosenoptions.order_id = refnumbers.order_id)
Looks like its working, but will some rows be left out? Have i done it wrong?
Upvotes: 0
Views: 67
Reputation: 15351
As far as I understand (w/o table definitions), you are dealing with 4 tables. To achieve what you want in one query, you have to join all tables and test orders_chosenoptions.product_id
using MySQL's IF()
to conditionally select either deals_products.price
OR deals.price
.
SELECT r.refno, IF(cp.product_id > 0, dp.price, d.price) AS price, r.order_id
FROM refnumbers r
JOIN deals d ON d.ID = r.deal_id
LEFT JOIN orders_chosenoptions oc ON r.order_id = oc.order_id
LEFT JOIN deals_product dp ON oc.product_id = dp.id
WHERE r.deal_id = ...
Upvotes: 2