I came across two tables something like this
product table -
id
product
1
product1
2
product2
product_inventory table -
product_id
quantity
1
5
2
1
3
9
the product_inventory tables product_id supposed to reference product tables id but let's say it doesn't so we have a product_id (and quantity) in Product inventory table that's not associated with any real product. Now imagine there are hundred thousands of invalid values like this so I can't manually remove them by id. So I find these using right joining both tables like this:
SELECT product.id, product_inventory.product_id
FROM product
RIGHT JOIN product_inventory ON product.id=product_inventory.product_id
where product.id is NULL;
so I get list of like this for example
product.id
product_inventory.product_id
1
5
2
1
NULL
9
so how do I delete from product_inventory table where product.id is NULL?
You can use:
delete pi from product_inventory pi
where not exists (select 1 from product p where p.id = pi.product_id);
You should also learn about foreign key relationships to prevent this from happening.
Related
I have a somewhat far-fetched question I want to know if there is any way to solve it:
I have a table called PRODUCTS with these attributes:
ID, NAME, DATE
I have a table called PRODUCTS_STATUS with these attributes:
ID, PRODUCT_ID, STATUS_ID, DATE
I have a table called STATES with these attributes:
ID, STATUS_NAME
Now, as you have seen, it will be about:
STATES_PRODUCTS will have many STATES of PRODUCTS and STATUS will be many times in PRODUCT_STATUS
This means that PRODUCT_STATUS has a many-to-many relationship between states and products, since a PRODUCT will go through different state transitions.
Perfect up to there, it turns out that I have this case suppose:
PRODUCTS_STATES
ID, PRODUCT_ID, STATUS_ID, DATE
1 1 1 00:00:00
2 2 1 00:00:00
3 3 1 00:00:00
4 1 5 00:00:00
I am doing a query at the moment between PRODUCTS and PRODUCT_STATUS, at first I made a query where I told him to show me all the PRODUCTS that have in PRODUCT_STATUS the STATUS_ID= 1
But if you realize for example the PRODUCT_ID is twice in the table PRODUCT_STATUS with the STATUS_ID = 1 and 5
Ask:
Is it possible to make a query where it shows me all PRODUCTS with PRODUCT_STATUS equal to 1 but where PRODUCTS_ID that already has another state are excluded?
that is, for this example, I want to know if we could see PRODUCTS 2 and 3 because if they see 1 it already has another state.
Notice I have this query made but it is not useful for what I want:
SELECT
*
FROM
products
inner join product_status in products.id = product_status.product_id
WHERE
product_status.status_id not IN (
SELECT
product_status.id_status
FROM
product_status
WHERE
product_status.id_status = 5
)
Obviously they will realize that the query returns all the products with STATUS_ID = 1 but I no longer want to see PRODUCT 1 because I am no longer interested.
I would like to exclude all those PRODUCTS that have 1 and 5.
I hope you can give me an idea of how it is done. Thanks.
I recommend NOT EXISTS instead of NOT IN, because NOT IN has strange behavior when working with NULL values (and EXISTS often optimizes better than IN).
But your version is quite close:
SELECT p.*
FROM products p JOIN
product_status ps
ON p.id = ps.product_id
WHERE ps.status_id = 1 AND
NOT EXISTS (SELECT 1
FROM product_status ps2
WHERE ps2.product_id = ps.product_id AND
ps2.status_id <> 1
);
Note that this introduces tables aliases (abbreviations for the tables). This makes the query easier to write and to read.
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)
So I have two tables:
products
id
name
product_variants
id
product_id
name
barcode
I want to select all products with one query containing one field with the amount of related variants and one field with all related barcodes (seperated by space).
So for example this output:
product_id product_name product_variant_count product_variant_barcodes
1 Product 1 3 1234567890 0987654321 5432109876
2 Product 2 1 6789054321
3 Product 3 2 1234509876 3456781290
Is this possible?
As mentioned in the comments GROUP_CONCAT is perfect for this.
Selecting from products and joining onto product_variants:
SELECT p.id, p.name, COUNT(pr.id) AS product_variant_count,
GROUP_CONCAT(pr.barcode SEPARATOR ' ') AS product_variant_barcodes
FROM products p
LEFT JOIN product_variants pr ON (p.id = pr.product_id)
GROUP BY p.id
Suppose I have a Product table, and a
id product
1 Apple
2 Bag
3 Cat
4 Ducati
and a Cart table
id user_id product_id
1 1 2
2 1 3
3 2 1
4 3 1
So, I want to look at a particular user and see what he/she does NOT have in their Cart.
In other words, in the above example
SELECT ...... WHERE user_id=1 .....
would return Apple and Ducati because User 1 already has Bag and Cat.
(This may well duplicate another question but there are so many variations I couldn't find the exact match and put in these simple terms may help)
Perform a left join from product to all products purchased by user1, which can be retrieved with a subselect in the join. This will cause all product id's that are not in user1's care to have null product ids. The where clause will select all null product id's meaning they will not have been in a users cart, essentially filtering purchased items.
select p.name
from product p
left join (select product_id, user_id
from cart where user_id = 1)
c
on p.id = c.product_id
where c.product_id is null;
SQL Fiddle: http://sqlfiddle.com/#!2/5318eb/17
Select
*
From Product p
Where p.id Not In
(
Select c.product_id
From Cart c
Where User ID = ____
)
SELECT product FROM product_table
WHERE product NOT IN
(SELECT product_id FROM cart_table WHERE user_id = 1);
This will give you all product for all users which are not in there cart.
select c.user_id,a.Product
from cart c Cross Join product a
left Join
cart b on b.product_id=a.id and c.user_id=b.user_Id
where b.product_id is null
group by c.user_id,a.Product
Sql Fiddle Demo
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;