MYSQL Join if available - mysql

I have two tables I want to join, products and campaign_products
The tables look like this.
TABLE product
id | name
TABLE campaign_products
id | fk_campaign | fk_product | note
and if it's of interest
TABLE campaign
id | name
In all cases I need all the products returned, and if there is a row in the campaign_products which matches then add the values of those columns in as well. (null otherwise).
Remembering that multiple products can be part of multiple campaigns.
Here is what I tried, and in this case it only returns products that have a reference in campaign_products or products that don't exist at all in campaign_products so if the product is in campaign_products for another campaign it won't show up in other campaigns that don't include that product.
SELECT
product.id productId,
product.name productName,
campaign_product.note
campaignProductNote
FROMproduct
LEFT JOIN campaign_products ON product.id = campaign_products.fk_product
WHERE campaign_products.fk_campaign = 2 OR campaign_products.fk_campaign IS NULL
"2" changes based on the campaign being looked up.
I can't think of a way to solve this problem, is there a simple solution I'm missing ?

All you need to do is move the condition in the WHERE clause into the ON clause like so:
SELECT
product.id productId,
product.name productName,
campaign_product.note
campaignProductNote
FROM product
LEFT JOIN campaign_products ON product.id = campaign_products.fk_product
AND (campaign_products.fk_campaign = 2 OR campaign_products.fk_campaign IS NULL)

Related

Need help on query sum total quantity show wrong output

Process:
When user buy item and check out then there's cart and cart items table to store the transaction.
1 cart_id have many item which stored in cart items table.
After purchase succeed, then will generate a purchase order id and stored in purchase order table .
In purchase order table, id_cart and status will be stored.
From here, i am trying to calculate quantity based on id_product or id branch or etc from the purchase made.
There is receiving and ordered quantity field, which in some cases quantity received field might be null, so i will take ordered quantity value.
This is my query
SELECT id_product,sum(DISTINCT(COALESCE(received_qty, quantity)))
FROM (SELECT C.id_cart,C.received_qty,C.quantity , P.id_product,
PO.id_purchase_order, PO.status
FROM (SELECT * FROM cart_items WHERE id_cart IN (SELECT id_cart FROM purchase_orders)) AS C
LEFT JOIN products as P on p.id_product = c.id_product
LEFT JOIN purchase_orders AS PO ON C.id_cart = PO.id_cart ) AS A
GROUP By A.id_product
Table data
The cart id in will be duplicated based on product's supplier. Because need to track and send separately to supplier.
Result
By right the product id for 1212 should be 1 and 1223 is 2, total qty =3.
What's wrong with my query ?
Your outer joins seem to cause multiplication of your data, but there are so many unnecessary layers of fluff in your query that I cant make it out exactly.
How about just this:
SELECT id_product, sum(COALESCE(received_qty, quantity)) AS Nmbr
FROM cart_items
GROUP BY id_product
If you want to make sure the cart is in your purchase_orders:
SELECT c.id_product, sum(COALESCE(c.received_qty, c.quantity)) AS Nmbr
FROM cart_items c
JOIN (SELECT DISTINCT id_cart FROM purchase_orders) p ON p.id_cart = c.id_cart
GROUP BY c.id_product

MySQL Query - Get Customers who have not bought all parts of a single product ID

Okay so I have 2 tables. One table for Product List and one table for Orders. There will be several of the same ProductID in my Table1 since each ProductID has several parts to it (IE: Part 1 of 7.)
The PartNumber will be a number. How do I design my query to find me all the customers who have purchased one of the part numbers, but not all the part numbers for a single product ID?
I'm just learning the basics of MySQL so any help would be much appreciated!
Table1 - Product List
UniqueIDKey
Product ID
PartNumber
Table2 - Orders
UniqueIDKey
Product ID Ordered
PartNumber Ordered
Customer ID
So an order might look like this:
UniqueIDKey: 77
Product ID Ordered: 1001
PartNumber Ordered: 3
Customer ID: 2000001
And, several rows of my Table1 - Product List might look like this:
UniqueIDKey Product ID PartNumber
77 1001 1
78 1001 2
79 1001 3
You need to know the total number of parts under each product prior
to knowing which customers bought some parts of a product but not the
whole.
The query enclosed by table alias B provides count of parts for
each product.
The query enclosed by table alias A provides for each
<customer,product> pair the total number of bought parts.
Now the rest is to match whether the total number of bought parts is
less than the total number of parts of a product.
In this approach the query would look like below:
SELECT
A.customer_id,
A.product_id,
A.total_parts_of_product_customer_purchased AS total_purchased,
B.total_parts,
B.total_parts - A.total_parts_of_product_customer_purchased AS didnot_purchase
FROM (
SELECT
customer_id,
product_id,
count(part_number) AS total_parts_of_product_customer_purchased
FROM Orders AS ordr
GROUP BY
customer_id, product_id
) AS A
INNER JOIN (
SELECT
product_id,
count(part_number) AS total_parts
FROM product_list AS pl
GROUP BY product_id
) AS B
ON A.product_id = B.product_id
WHERE A.total_parts_of_product_customer_purchased < B.total_parts
ORDER BY A.customer_id;
Use a cross join to get all combinations of customers,product_id's and part_numbers. left join orders table on to this result to get customers who haven't ordered all the parts in a product.
select c.customer_id,p.product_id
from (select product_id,part_number from product_list) p
cross join (select distinct customer_id from orders) c
left join orders o on p.product_id=o.product_id and p.part_number=o.part_number and c.customer_id=o.customer_id
group by c.customer_id,p.product_id
having count(o.part_number) < count(p.part_number)

Search query with id

This are my tables:
Part table:
Part_id name
1 Case
2 Pen
3 Chicken
(Between table)table:
Part_id product_id
2 10
2 10
3 30
Product table:
product_id Name
10 Phone
20 Camera
30 Mouse
I want to search on the product name and get the product name back + the linked part name. But if i search on part name i want to get the part name and product name back.
I don't know how to join the tables but don't know how to preform an search like that.
Select part.name, product.name
from part
left join betweentable on part.part_id = betweentable.part_id
But i don't know how to join the next table. And than search to it.
Let me see if I understand this correctly... you have a name, which may be a product name or a part name, and you want to search for that, and return the linked parts if it's a product, or the linked products if it's a part.
If that's what you're asking, you can use the following query:
Select part.name, product.name
from part
left join betweentable on part.part_id = betweentable.part_id
left join product on product.id = betweentable.product_id
where part.name = <input_name>
union
Select part.name, product.name
from product
left join betweentable on product.id = betweentable.product_id
left join part on part.part_id = betweentable.part_id
where product.name = <input_name>;
< input_name > is the name you're searching for.
Simply add an other join:
Select part.name, product.name
from part
left join betweentable on part.part_id = betweentable.part_id
left join product on product.id = betweentable.product_id

Reading a database diagram

I've been trying to figure out how to get the products that match a certain category id but I have been unable to figure out how to move from category to products.
How would a query that basically selects all products that match a certain category id look?
This should work:
SELECT products.*
FROM products,
product_category
WHERE product_category.categoryid = CATEGORY_ID
AND products.catalogid = product_category.catalogid
Or if you prefer a join:
SELECT products.*
FROM products
INNER JOIN product_category ON products.catalogid = product_category.catalogid
WHERE product_category.categoryid = CATEGORY_ID
Simply replace CATEGORY_ID by the ID of the category you wish to select.
product_category is a link table, joining the tables products and product_category together: it contains the catalogid, referencing the ID of the category, and catalogid, referencing the ID of the product.

Inverse of Inner join (Intersect) with multiple foreign keys

Hi I want to get opposite of intersect from two tables.
I have a sale table and purchase table. What I want to do is get all purchases ids where not included in the sales table.
sale table
sale_id (pk)
product_id (fk)
purchase_id (fk)
purchase table
product_id (fk)
purchase_id (pk)
SELECT DISTINCT purchase_id
, product_id
FROM
purchase
INNER JOIN sale
USING (purchase_id, product_id);
Here is an example:
If I run the above code, this will be the result.
purchase_id product id
1 1
1 2
1 4
2 1
2 3
Now I want to get:
purchase_id product id
1 3
2 2
In short I want to get inverse of above code. Thanks in advance.
Okay, I think I understand better now.
This should return any entry in purchase that have no matching entry in sales.
SELECT
`purchase`.`purchase_id`, `purchase`.`product_id`
FROM `purchase`
LEFT JOIN `sale` ON `sale`.`purchase_id` = `purchase`.`purchase_id` AND `sale`.`product_id` = `purchase`.`product_id`
WHERE
`sale`.`sale_id` IS NULL
ORDER BY
`purchase`.`purchase_id`, `purchase`.`product_id`
If you want to get all the purchases that have no related values in the sales table, you can use a LEFT JOIN:
select
p.purchase_id
from
purchase as p
left join sale as s on p.purchase_id = s.purchase_id
where
s.purchase_id is null;
"Unilateral" joins (LEFT JOIN, RIGHT JOIN) are useful when you want to get data from a table even if data in another related table does not exist. Of course, that means that you can filter data from one table when there's no related data in a second table.
Hope this helps.
Looking at your updated question and your comment, I think that you want all the possible combinations not used.
You'll need to split this in two steps:
First you need all the possible combinations of purchase_id and sale_id values (the "cartesian product" of both the sets).
Then you need to get all the combinations already used.
Finally you need to exclude all the combinations already used.
This can be done using subqueries.
Step 1.
select distinct p.purchase_id, s.product_id from purchase as p, sale as s;
Step 2. (Your query)
select distinct
purchase_id, product_id
from
purchase as p
inner join sale as s
on (p.purchase_id = s.purchase_id and p.product_id = s.product_id);
Step 3. Put it all together
select
a.*
from
(select distinct p.purchase_id, s.product_id from purchase as p, sale as s) as a
left join (
select distinct
purchase_id, product_id
from
purchase as p
inner join sale as s
on (p.purchase_id = s.purchase_id and p.product_id = s.product_id)
) as e on (a.purchase_id = e.purchase_id and a.product_id = e.product_id)
where
e.purchase_id is null and e.product_id is null;