mysql find records against multiple row condition - mysql

So here I have multiple table and joined them but here I have put simple example like:
here i am able to find all those items who has category_id 1 and 3 any one using in query, but now i need and condition here like where category 1 and 3 both matches.
here i need all those items who has category_id 1 and 3 both.
So how to do that?
mysql in query is matching anyone exist, so is there any other function which matches multiple values?

Using INNER JOIN with a subquery to get the items that have both category_id 1 and 3. The subquery would select all the item_id's that have category_id 1 or 3 and the main query would join with the subquery on the item_id.
SELECT p1.item_id, p1.product_id, p1.category_id
FROM PRODUCT p1
INNER JOIN (
SELECT item_id
FROM PRODUCT
WHERE category_id IN (1, 3)
GROUP BY item_id
HAVING COUNT(DISTINCT category_id) = 2
) p2 ON p1.item_id = p2.item_id
WHERE p1.category_id IN (1, 3);
Sample:
-- create
CREATE TABLE PRODUCT (
id INTEGER PRIMARY KEY,
item_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
category_id INTEGER NOT NULL
);
-- insert
INSERT INTO PRODUCT VALUES (3862, 297,0, 1);
INSERT INTO PRODUCT VALUES (3861, 297,0, 3);
INSERT INTO PRODUCT VALUES (3860, 23, 0,1);
Output:
item_id product_id category_id
297 0 3
297 0 1

Related

MYSQL how to check if there are multiple rows other than value x

I have a mapping table that maps certain ID's to eachother (products and categories). Now I need to check whether or not in this mapping category there are multiple rows. For example every product has a standard mapping of category id of 1. Now there could be more rows that have other category id's. For example:
Product_id Category_id
1 1
1 2
2 1
3 1
4 1
4 2
I need to only select those rows that only have the product id and the category id of 1. So in this case I want to selct product with id 2,3. Because 1 and 4 have multiple category id's.
I have this query (it's a join because I want to add some other data in this query):
SELECT * FROM `products` as P
LEFT JOIN `product_categories` as PC
ON PC.`product_id` = P.`product_id`
WHERE PC.`category_id` = 1 AND
LIMIT 10
Now I don't know exacly what I need to do in the Where statement. Can anyone help me?
I thought about using count, but I don't think that is the best solution. Maybe check if there are other values other than 1 in the category id or something?
I have considered your table as a reference. You can add or perform join after that.
You can not add where here. The count is a group function (also called aggregate function). So you have to add having instead of where.
Creating the table:
CREATE TABLE IF NOT EXISTS `test` (
`product_id` int(6) unsigned NOT NULL,
`category_id` int(6) unsigned NOT NULL
) DEFAULT CHARSET=utf8;
INSERT INTO `test` (`product_id`, `category_id`) VALUES
(1,1),
(1,2),
(2,1),
(3,1),
(4,1),
(4,2)
Result generation SQL:
select product_id,category_id
from test group by product_id having count(product_id)<2
Output:
product_id category_id
---------- ------------
2 1
3 1

How to apply mysql join on a column having array field in table?

I have two tables
users, products
users table
id product_id
1 [1,2,3]
2 [5,6]
3 [4]
Products table
id product
1 Milk
2 Bread
3 Soup
4 Noodles
6 Suger
7 Biscuits
8 Raw Eggs
How to apply joins on these tables.
Here is what i am trying to do.
select * from products join users ON find_in_set(products.id, users.product_id)
But, The output is incorrect.
Please guide me how to implement this.
Here's how to fix it:
CREATE TABLE user_products (
user_id INT,
product_id INT,
PRIMARY KEY (user_id, product_id)
);
Fill one user and one product id into each row.
INSERT INTO user_products (user_id, product_id)
VALUES (1,1), (1,2), (1,3), (2,5), (2,6), (3,4);
Now you can do the join this way:
SELECT * FROM users AS u
JOIN user_products AS up ON u.id = up.user_id
JOIN products AS p ON up.product_id = p.id;
Don't use JSON arrays for joins.
This is working for me for few data from your sample instead of find_in_set i would recommend you use REGEXP_LIKE
WITH USERS AS (
SELECT 1 AS ID , '[1,2,3]' AS product_id UNION ALL
SELECT 2, '[5,6]' UNION ALL
SELECT 3, '[4]'
),
PRODUCTS AS (
SELECT 1 AS ID , 'Milk' AS PRODUCT UNION ALL
SELECT 2, 'Bread' UNION ALL
SELECT 3, 'Soup' UNION ALL
SELECT 4, 'Noodles'
)
select * from PRODUCTS join USERS ON REGEXP_LIKE(USERS.PRODUCT_id, PRODUCTS.id);
this is the query :
select * from PRODUCTS join USERS ON REGEXP_LIKE(USERS.PRODUCT_id, PRODUCTS.id)
output im getting is
# ID, PRODUCT, ID, product_id
1, Milk, 1, [1,2,3]
2, Bread, 1, [1,2,3]
3, Soup, 1, [1,2,3]
4, Noodles, 3, [4]

Using AND (OR) to select based on multiple row values

I want to create filter query which uses AND and OR on many to many relation table.
Table consists only of 2 columns id_product and id_category
My query I'm using, but its not working:
SELECT id_product FROM id_category WHERE ( id_category = 1) AND (id_category = 2)
AND ( id_category = 3 OR id_category = 4 OR id_category = 5) GROUP BY id_product
I would like to retrieve products that are in categories at the same time.
Only IDs of products which are in category 1 AND 2 AND (3 or 4 or 5)
You must group by id_product and put these conditions in a HAVING clause:
SELECT id_product
FROM tablename
GROUP BY id_product
HAVING
SUM(id_category = 1) > 0
AND
SUM(id_category = 2) > 0
AND
SUM(id_category IN (3, 4, 5)) > 0
Just for fun, to use a single condition in the HAVING clause:
SELECT id_product
FROM yourTable
WHERE id_category BETWEEN 1 AND 5
GROUP BY id_product
HAVING
COUNT(DISTINCT CASE WHEN id_category IN (3, 4, 5)
THEN 3 ELSE id_category END) = 3;
Demo
The logic here is to first restrict the query to only id_category values (1,2,3,4,5). Then, we assert but first map id_category values of (3,4,5) to the same single value 3. The assertion is that the distinct count of mapped id_category values is 3, which would imply that 1, 2, and (3,4,5) all occur for that product.

SELECT from table WHERE value across multiple rows

I have a table that maps products to categories. Each product can belong to multiple categories, so a product can have multiple rows with different category IDs. It looks something like this:
CREATE TABLE `products_mid` (
`id` int(11) UNSIGNED NOT NULL,
`product_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`category_id` int(11) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
If I want to get a list of all product IDs that are in category A that's simple enough-- but is there a way to get all product_ids where they belong to categories A, B and C as simply as possible?
A better approach is to do it with HAVING clause, not a WHERE clause. Group by product_id, and select rows having non-zero count of each of your three categories, like this:
SELECT product_id
GROUP BY product_id
HAVING SUM(CASE WHEN category_id=1 THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN category_id=2 THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN category_id=3 THEN 1 ELSE 0 END) > 0
The above statement selects product_ids of products that belong to all three categories with IDs 1, 2, and 3.
It will be something like this:
select product_id from products_mid
where
category_id in (1,2,3)
group by product_id
having count(distinct category_id)=3
Use the intersect operator to find the common values of three separate queries.
select product_id from products_mid where category_id = 1
intersect
select product_id from products_mid where category_id = 2
intersect
select product_id from products_mid where category_id = 3
Another way:
SELECT product_id
FROM products_mid
WHERE category_id IN (1, 2, 3)
GROUP BY product_id
HAVING COUNT(DISTINCT category_id) = 3
This would find all products in categories 1 through 3, although a product could also belong to other categories. If you want products which exclusively belong to category 1 through 3, and no others, then we would have to rephrase the query.

Easiest Way Of Copying a Row in MySQL

what's the easiest way of to clone a row with a different ID in MySQL.
For example:
Products
product_id name price
------------------------
1 a 10
2 b 15
It looks like weird, but I need to clone product with id = 1. So the table will look like:
Products
product_id name price
------------------------
1 a 10
2 b 15
3 a 10
You can use subqueries:
INSERT INTO
donation (name,price)
SELECT name,price
FROM donation
WHERE product_id = 1
INSERT INTO Products (name, price) VALUES ((SELECT name FROM Products WHERE product_id = 1), (SELECT price FROM Products WHERE product_id = 2));
INSERT INTO Products (name, price)
VALUES
((SELECT name, price
FROM Products
WHERE product_id = 1));
If you want to clone a row with a single SQL statement and can't or don't want to list all the values but there is a primary key you can use:
INSERT INTO Products
SELECT *
FROM Products
WHERE product_id = 1
UNION ALL
SELECT *
FROM Products
WHERE product_id = 1
ON DUPLICATE KEY UPDATE product_id=(SELECT MAX(product_id)+1 FROM Products);
This tries to insert two copies of the row into the databse and when the first row insert fails due to a duplicate product_id it uses ON DUPLICATE KEY to update the existing row in the table to the next available product_id, which leaves the original product_id available for when the second row is inserted.