MySQL - Using FIND_IN_SET on Multiple Tables with No Relation - mysql

My database structure looks something as follows:
Database Name: Products
id ptype
1 Cups
2 Shirts
3 Cups
4 Mugs
5 Fabric
6 Mat
Database Name: Categories
id category ptype
1 Clothes Pants, Shirts, Tshirts
2 Other Mugs, Cups
I want to get a list of distinct ptype (products table) which aren't already listed in ptype of categories table
So the result would be
ptype
Fabric
Mat
I tried using the following mysql select query but it doesn't seem to work
SELECT p.ptype, c.ptype, FIND_IN_SET(p.ptype,c.ptype) FROM products as p, categories as c WHERE FIND_IN_SET(p.ptype,c.ptype) < 1
It returns value of FIND_IN_SET as 0 for all the ptypes of products table.

Remove the spaces after the commas in categories.ptype field to make the query work. find_in_set() compares the needle to a list of comma separated values and considers the space after the commas to be part of the strings it searches, therefore no match is found if you search for a string that does not contain the spaces.

Related

Select all rows contains same value in a column

I want to select all package_id that contain product_id 2.
In this case, package_id 1,3,5 has product_id 2
Table: product_package
package_id package_name product_id
---------------------------------------------
1 Gold 1,2,3
2 Platinum 4,5,12
3 Diamond 2,11,5
4 Titanium 3,5
5 Basic 2
I tried:
SELECT
*
FROM
product_package
WHERE product_id IN(2)
It is outputting package_id 3 and 5 only. How do I output this properly?
product_id structure is varchar(256). Should I change the structure or add Foreign keys?
We always recommend not to stored delimited columns see Is storing a delimited list in a database column really that bad?
But you can use FIND_IN_SET but this is always slow
SELECT
*
FROM
product_package
WHERE FIND_IN_SET(2,product_id)
package_id
package_name
product_id
1
Gold
1,2,3
3
Diamond
2,11,5
5
Basic
2
fiddle
First, let me explain what is happening in your query.
You have WHERE product_id IN(2), but product_id is a misnomer and should rather be product_ids, because it is multiple IDs unfortunately stored in a string. IN is made to look up a value in a list. Your list, however, only consists of one element, so you can just as well use the equality operator: WHERE product_id = 2.
What you have is WHERE string = number, so the DBMS has to convert one of the values in order to compare the two. It converts the string to a number (so '2' matches 2 and '002' matches 2, too, as it should). But your strings are not numbers. The DBMS should raise an error on '1,2,3' for instance, because '1,2,3' is not a number. MySQL, however, has a design flaw here and still converts the string, regardless. It just takes as many characters from the left as they still represent a number. '1' does, but then the comma is not considered numerical (yes, MySQL cannot deal with a thousand separator when convertings strings to numbers implicitly). So converting '1,2,3' to a number results in 1. Equally, '2,11,5' results in 2, so rather surprisingly '2,11,5' = 2 in MySQL. This is why you are getting that row.
You ask "Should I change the structure", and the answer to this is yes. So far your table doesn't comply with the first normal form and should thus not exist in a relational database. You'll want two tables instead forming the 1:n relation:
Table: package
package_id
package_name
1
Gold
2
Platinum
3
Diamond
4
Titanium
5
Basic
Table: product_package
package_id
product_id
1
1
1
2
1
3
2
4
2
5
2
12
3
2
3
11
3
5
4
3
4
5
5
2
You ask "or add Foreign keys?", and the answer is and add foreign keys. So with the changed structure you want product_package(product_id) to reference product(product_id) and product_package(package_id) to reference package(package_id).
Disregarding that you should not be storing multiple values in a single field, you can use LIKE operator to achieve what you are looking for. I'm going with assumptions:
all values are delimited with commas
all values are integers
there are no whitespaces (or any other characters besides integers and commas)
select * from product_package
where product_id like '2,%'
or product_id like '%,2,%'
or product_id like '%,2'
or product_id like '2'
Alternatively, you can use REGEXP operator:
select * from product_package
where product_id regexp '^2$|^2,.+|.+,2,.+|.+,2'
References:
MySQL LIKE
MySQL REGEXP

How to do a "SELECT DISTINCT" with two "INNER JOIN"?

What I'm trying to do is to GetAPersonByID by doing some inner joins from different tables.
TABLE PEOPLE
IDPerson
Name
LastName
E-mail
fk_ID_Skin
1
Example
Explanation
help#please.com
1
2
Example2
Explanation
ineed#somebody.com
2
TABLE SKINS
IDSkin
Name
1
Normal
2
Weird
TABLE PRODUCTS
IDProduct
Name
fk_skin_type
Photo
1
Oil
1
PhotoOil
2
Water
2
PhotoWater
3
Cream
2
PhotoCream
I need to know which products the CUSTOMER should use according to their SKIN TYPE
But... When I tried to do the InnerJoins (My apologies for the Spanish text in the database):
SELECT
people.IDPerson AS 'Id_person',
people.name AS 'Name',
people.lastname AS 'Lastname',
people.email AS 'E-mail',
skins.name AS 'Skin',
products.name AS 'Product',
products.photo AS 'Photo'
FROM
((people
INNER JOIN skins
ON people.fk_ID_skin = skins.IDSkin)
INNER JOIN products
ON people.fk_ID_skin = products.fk_skin_type)
WHERE IDPerson = c_id;
How can I show 'X Person' without repeating the data?
I'm using MySQL Workbench
How can I show 'X Person' without repeating the data?
It sounds like you are saying you want to see only 1 row per person? Assuming that's the case then I think what you are looking to do is GROUP BY IDPerson. Then you could use the GROUP_CONCAT function in your SELECT statement to generate a comma separated list of the values Foto, Producto, etc.

MS Access convert rows to columns using pivot

I have a table with ~6500 products and images in which each product can have several jpg files:
ID_product product product_photo ordering
1 Product A a1234.jpg 1
2 Product B x5678.jpg 0
3 Product A b1234.jpg 0
4 Product B y5678.jpg 1
5 Product B z5678.jpg 2
6 Product C e4455.jpg 1
7 Product C f4455.jpg 0
8 Product C g4455.jpg 2
So I created a query in MS ACCESS:
TRANSFORM First([table1].product_photo) AS product
SELECT [table1].ID_product, First([table1].product) AS products
FROM [table1]
GROUP BY [table1].ID_product
PIVOT [table1].product_photo;
The result of the query:
ID_product product a1234_jpg b1234_jpg e4455_jpg f4455_jpg g4455_jpg x5678_jpg y5678_jpg z5678_jpg
1 Product A a1234.jpg b1234.jpg
2 Product B x5678.jpg y5678.jpg z5678.jpg
3 Product C e4455.jpg f4455.jpg g4455.jpg
I would like to change the table in such a way that the images are in columns:
ID_product product image_1 image_2 image_3
1 Product A a1234.jpg b1234.jpg
2 Product B x5678.jpg y5678.jpg z5678.jpg
3 Product C e4455.jpg f4455.jpg g4455.jpg
How to expand the query to get the desired result?
Because the Pivot works on the value of the column rather than its name, you are out of luck. This is the problem with pivoting - it's fairly limited in its flexibility.
At this point, you usually revert to code. For example, you could build the result set in VBA in an array of arrays of variant.
Or, you could use VBA to count the maximum number of columns for any product, create a temp table with appropriately named columns, and insert the values into the appropriate rows.
Either way, this is really a UI issue of sexy display to the user, rather than handing off data from one query to the next, which is what SQL is designed for.

exact search and similar search combining two tables with multiple keywords mysql

Say I've two tables products and brands having below data.
tbl_products
ID Name BrandID Price
1 Keyboard 1 100
2 Keyboard 2 120
3 Keyboard wireless 1 130
4 Keyboard wireless 2 150
tbl_brands
ID Name
1 Microsoft
2 Dell
3 HP
What I want is when I type 'Microsoft Keyboard' or 'Keyboard Microsoft' then it should list me product ID 1 and 3 not 2 or 4 even 2 or 4 has keyboard. I may search for more keywords but it should give me only the items matching itself.
SELECT p.*, b.Name BrandName FROM tbl_products p INNER JOIN tbl_brands b ON b.ID = p.BrandID WHERE p.Name LIKE '%Microsoft%' OR b.Name LIKE '%Microsoft%' OR p.Name LIKE '%Keyboard%' OR b.Name LIKE '%Keyboard%'
Please help me to write proper MySQL query or any schema change with query..
Appreciate the question. Though I don't have exact answer but surely can discuss one approach to solve the problem.
STEP 1 Get BRAND NAME+NAME as single string.
STEP 2 Tokenise the entered STRING. Example Microsoft Keyboard = Mincrosoft,Keyboard Following Link for spliting the entered data. How do I split a string so I can access item x?
STEP 3 DO a like query on the string obtained in step 1.

MySQL - Search for record within nested tables

I have a MySQL database with two tables. The first is a hierachy of departments, whereby each record has a parent record from within the same table, and the top level has a parent_id of 0.
The second is a table of products. Each product can live anywhere in the tree of departments.
I need to be able to let people search for a product by specifying a department to search within, but for the search to look within all the sub-departments of the specified department. Can this be done in a single query?
My "Plan B" is to store a list of parent ids with each product in a new field, and search that field using a LIKE query, but that seems nasty somehow.
Dummy data:
id|parent_id|name
1|0|Main 1
2|0|Main 2
3|0|Main 3
4|1|Sub 1-1
5|1|Sub 1-2
6|1|Sub 1-3
7|4|Sub 1-1-1
8|4|Sub 1-1-2
9|4|Sub 1-1-3
id|department|product
1|1|test product 1
2|4|test product 2
3|7|test product 3
SELECT * FROM products WHERE department = 1 ; want to receive all three products
SELECT * FROM products WHERE department = 4 ; want to receive products 2 and 3
SELECT * FROM products WHERE department = 7 ; want to receive only product 3