Reputation: 3063
So I have written a query that will grab an order (this is for an ecommerce type site), and from that order id it will get all order items (ecom_order_items), print options (c_print_options) and images (images). The eoi_p_id is currently a foreign key from the images table.
This works fine and the query is:
SELECT eoi_parentid, eoi_p_id, eoi_po_id, eoi_quantity, i_id, i_parentid, po_name, po_price FROM ecom_order_items, images, c_print_options WHERE eoi_parentid = '1' AND i_id = eoi_p_id AND po_id = eoi_po_id;
The above would grab all the stuff I need for order #1
Now to complicate things I added an extra table (ecom_products), which needs to act in a similar way to the images table. The eoi_p_id can also point at a foreign key in this table too. I have added an extra field 'eoi_type' which will either have the value 'image', or 'product'.
Now items in the order could be made up of a mix of items from images or ecom_products. Whatever I try it either ends up with too many records, wont actually output any with eoi_type = 'product', and just generally wont work. Any ideas on how to achieve what I am after? Can provide SQL samples if needed?
SELECT eoi_id, eoi_parentid, eoi_p_id, eoi_po_id, eoi_po_id_2, eoi_quantity, eoi_type, i_id, i_parentid, po_name, po_price, po_id, ep_id FROM ecom_order_items, images, c_print_options, ecom_products WHERE eoi_parentid = '9' AND i_id = eoi_p_id AND po_id = eoi_po_id
The above outputs duplicate rows and doesnt work as expected. Am I going about this the wrong way? Should I have seperate foreign key fields for the eoi_p_id depending it its an image or a product?
Should I be using JOINs?
Here is a mysql explain of the tables in question
ecom_products +-------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+----------------+ | ep_id | int(8) | NO | PRI | NULL | auto_increment | | ep_title | varchar(255) | NO | | NULL | | | ep_link | text | NO | | NULL | | | ep_desc | text | NO | | NULL | | | ep_imgdrop | text | NO | | NULL | | | ep_price | decimal(6,2) | NO | | NULL | | | ep_category | varchar(255) | NO | | NULL | | | ep_hide | tinyint(1) | NO | | 0 | | | ep_featured | tinyint(1) | NO | | 0 | | +-------------+--------------+------+-----+---------+----------------+ ecom_order_items +--------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+-------------+------+-----+---------+----------------+ | eoi_id | int(8) | NO | PRI | NULL | auto_increment | | eoi_parentid | int(8) | NO | | NULL | | | eoi_type | varchar(32) | NO | | NULL | | | eoi_p_id | int(8) | NO | | NULL | | | eoi_po_id | int(8) | NO | | NULL | | | eoi_quantity | int(4) | NO | | NULL | | +--------------+-------------+------+-----+---------+----------------+ c_print_options +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | po_id | int(8) | NO | PRI | NULL | auto_increment | | po_name | varchar(255) | NO | | NULL | | | po_price | decimal(6,2) | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ images +--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+----------------+ | i_id | int(8) | NO | PRI | NULL | auto_increment | | i_filename | varchar(255) | NO | | NULL | | | i_data | longtext | NO | | NULL | | | i_parentid | int(8) | NO | | NULL | | +--------------+--------------+------+-----+---------+----------------+
Upvotes: 2
Views: 2382
Reputation: 52645
You're missing a join condition for ecom_products either in the WHERE or FROM Clause. This is how it would be done using ANSI-92 joins
SELECT
eoi_id,
eoi_parentid,
eoi_p_id,
eoi_po_id,
eoi_po_id_2,
eoi_quantity,
eoi_type,
i_id,
i_parentid,
po_name,
po_price,
po_id,
ep_id
FROM
ecom_order_items,
LEFT JOIN images
ON i_id = eoi_p_id
LEFT JOIN c_print_options
ON po_id = eoi_po_id
INNER JOIN ecom_products
ON eoi_p_id = ep_id
WHERE
eoi_parentid = '9'
ANSI 92 joins are preferred and its a little clearer what's a join and what's filtering. That said you could just add AND eoi_p_id = ep_id
to you where clause.
Upvotes: 2
Reputation: 11380
This is how I'd write the first query. I prefer to use joins.
SELECT eoi_parentid, eoi_p_id, eoi_po_id, eoi_quantity, i_id, i_parentid, po_name, po_price
FROM ecom_order_items
INNER JOIN images
ON i_id = eoi_p_id
INNER JOIN c_print_options
ON po_id = eoi_po_id
WHERE eoi_parentid = '1'
For your second query I would use a UNION on two queries, one for images and one for products.
SELECT eoi_id, eoi_parentid, eoi_p_id, eoi_po_id, eoi_po_id_2, eoi_quantity, eoi_type, i_id, i_parentid, po_name, po_price, po_id, ep_id
FROM ecom_order_items
INNER JOIN images
ON i_id = eoi_p_id
INNER JOIN c_print_options
ON po_id = eoi_po_id
WHERE eoi_type = 'image' AND i_id = eoi_p_id --Image conditions
AND eoi_parentid = '9'
AND po_id = eoi_po_id
UNION
SELECT eoi_id, eoi_parentid, eoi_p_id, eoi_po_id, eoi_po_id_2, eoi_quantity, eoi_type, i_id, i_parentid, po_name, po_price, po_id, ep_id
FROM ecom_order_items
INNER JOIN images
ON i_id = eoi_p_id
INNER JOIN c_print_options
ON po_id = eoi_po_id
WHERE eoi_type = 'product' AND ep_id = eoi_p_id -- Product conditions
AND eoi_parentid = '9'
AND po_id = eoi_po_id
Upvotes: 1