Search by serialized value - php

This is the query i use for getting the data out of my database
SELECT
product_description.name as name,
product.image as iurl
FROM
product_description, product
WHERE
product_description.product_id = product.product_id
AND product.product_id
AND product.product_id = '33';
Why is this query producing double results?
I want to automaticly search by multiple values (id's) stored in database instead of manually adding the AND product.product_id='?' part. Values are stored in serialized form.
something like
... AND product.product_id in (setting.value WHERE key='featured');
I know that query is not correct, just trying to show what i want.
table 'setting':
value | key
-------------------
23,43,28 | featured

Solution
To get the details of all products which are stored in your settings table (comma separated) you can use FIND_IN_SET()
SELECT
product_description.description,
product.name,
product.id
FROM
product_description, product
WHERE
product_description.id = product.id
AND FIND_IN_SET(product.id, ( SELECT value FROM setting where `key` = 'featured' ) );
SQLFiddle
Note: The reason why you see duplicated entries could be because there are multiple descrioptions for a particular product, you can handle this using GROUP_CONCAT
The following should work
Epilogue
Your database design is not good, It should be something like
product -- All my products go here
product_details -- Details of all the products ( A product could have multiple details)
categories -- eg: Featured, Seasonal
product_categories -- association of product to categories

This is somehow breaking the relational paradigm, you should have three entries with values 23, 43 and 28.
Then again I'm guessing field value is a varchar (do you know "value" and "key" are reserved words by mysql ?) so you might want to look inside the string to find pattern ",23," inside the field. Something like : WHERE CONCAT(',', field_value, ',') LIKE "%,23,%"

Related

MySQL Query to find all subscriptions to a tag where all values match

I'm struggling to articulate what I'm trying to achieve.
I have a product which can be assigned many tags, I then have a subscription table which holds the productID and the tagID.
I'd like to search the subscription table in the most efficient way to see if a product is subscribed to ALL tags (not ANYthat I provide).
I've tried many things including this:
SELECT
productID
FROM productTagSubscription
WHERE tagID IN ( 'id1', 'id2', 'id3', 'id4');
So the product has to be subscribed to all 4 ID's as 4 rows in the subscription table
This is then pulling back any records for ANY id, which isn't what I'm trying to achieve - any advice appreciated!!
Table Structure:
Expected Output
My expected output when passing all 3 or 4 tagID's into the table would give me a list of products that all subscribe to all tags provided.
You can count the diferent tagID for each product.
SELECT productID
FROM productTagSubscription
GROUP BY productID
HAVING COUNT(tagID) = 4; /* total amount of tags */
In many pivot tables, you can find a unique pair key, in this case between (productID, tagID), if that's not the case make sure tagID are DISCTINCT.
HAVING COUNT(DISCTINCT(tagID)) = 4;
as long as I change the COUNT number to match the number of tags I'm looking for
If you want to avoid the number, assuming that all tags are been used in one or another product.
HAVING COUNT(DISCTINCT(tagID)) = (
SELECT MAX(DISCTINCT(tagID))
FROM productTagSubscription
);
HAVING COUNT(DISCTINCT(tagID)) = (
SELECT COUNT(*) FROM tags
);

Unique Columns in SQL Views

In my database I have one table that contains a complete list of products, and another table that contains the same list of products on the x-axis, with a list of customers on the y-axis, where the value for each product can be 1 or 0 depending on whether that customer can view that product. My SQL looks like this:
SELECT products.product_code, products.product_type, products.product_category, products.product_title, products.product_description
FROM product_lists
INNER JOIN products
ON product_lists.product_code=products.product_code
WHERE product_lists.customer="1"
ORDER BY products.product_code
My problem is that I would like to create a view of this result for each customer to use as that customers product table, however when I create it I get the message "This table does not contain a unique column. Grid edit, checkbox, Edit, Copy and Delete features are not available." even though the product_code field is set as a primary key in both the products table and the product_lists table.
How can I create a join/view that uses the primary key from the table(s) it was created from? In short I would like the product_code field to become the primary key of my view.
Thanks!
I think the problem is the join. You can fix this by moving the condition to the where clause. MySQL doesn't allow subqueries in the from, but it does in the where:
SELECT p.product_code, p.product_type, p.product_category, p.product_title, p.product_description
FROM products p
WHERE EXISTS (SELECT 1
FROM product_lists pl
WHERE pl.product_code = p.product_code AND
pl.customer = 1
)
ORDER BY p.product_code;

MySQL Merge 3 Tables into 1

I am creating a search box in PHP and using MySQL as the database but when searching there are 3 tables, Colours, Products and Categories, these all have an ID number and can be linked. I have tried to use INNER JOIN, LEFT, RIGHT, everywhere but no luck, the query will sometimes work, spit out multiple items. So I am looking at creating a one-table-fits-all scenario where all the table field names will be in one and I can easily query that table. I have manually created the table but is there anyway of coping the data from the 3 tables into that main one? I do not mind doing it separately if it is a query that only handles one table but I would love not to have to manually type all the data as there is 600+ rows.
Here is the code I am currently trying to use:
SELECT
categories.Product_Type, items_colors.ColourImageurl,
items_list.description, items_list.Description2,
items_list.title, items_list.id, categories.title AS title2,
items_colors.itemID, Colour Name
FROM items_list
LEFT JOIN categories ON categories.Product_Type = items_list.CatID
LEFT JOIN items_colors ON items_list.id = items_colors.itemID
WHERE items_list.visible = 1 AND
Colour Name LIKE '%".$search."%'
Categories defines what type of product you are selecting, items_list has a list of all the sub category names and item_colors has a list of all the colour names that link to the items_list products. When I use this query it outputs 4 copies of one item and I'm not sure why.
If you are getting data from a query, you can use "create table as select" statement to create the new table, with data from old tables.
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
[(create_definition,...)]
[table_options]
[partition_options]
select_statement
check here for more info : http://dev.mysql.com/doc/refman/5.1/en/create-table.html

Order a SQL Query by number of results

I want to do the following:
$searchParams is an array, which contains some strings (dynamicly generated).
Now the Statement would be something like this:
SELECT manufacturer FROM shop_articles WHERE manufacturer LIKE '".$searchParams."%'
But what I want is the result with the most matches. Can I code that in one statement?
So it would be something like
ORDER BY MATCHES DESC
How do I do that?
SELECT COUNT(*) AS matches, manufacturer FROM shop_articles WHERE manufacturer LIKE '".$searchParams."%' GROUP BY(manufaturer) ORDER BY matches ASC
For each param in your searchParam array you have to make a like clause
SELECT Manufacturer, COUNT(*) AS Matches FROM
FROM shop_articles WHERE (
manufacturer LIKE '".$searchParams[0]."%' OR
manufacturer LIKE '".$searchParams[1]."%' OR
...
manufacturer LIKE '".$searchParams[n]."%' OR )
GROUP BY Manufacturer
ORDER BY Matches
Actually you have to measure matching (likeness) between manufacturer and $searchParam. Unfortunatelly LIKE does not provide such functionality.
You may use Lavenshtein distances. See this post - Implementation of Levenshtein distance for mysql/fuzzy search?
SELECT manufacturer, COUNT(manufacturer) FROM shop_articles WHERE manufacturer LIKE '".$searchParams."' GROUP BY manufacturer ORDER BY COUNT(manufacturer) DESC
No, you cannot submit an array to the LIKE operator. It is more tedious than that. :-)
When your data are not yet properly regularized, so that you have variants of the manufacturer name in the PRODUCTS table (e.g. "HP", "Hewlett Packard") rather than an integer ManufacturerID, you have to go through the grunt work of reducing those variants to a single entity.
A typical approach for doing that (quite unavoidable) work is to create a Manufacturers table like this:
Table: MANUFACTURER
manufacturerid INTEGER primary key
manufacturername varchar
primarymanufacturerid INTEGER FOREIGN KEY REFERENCES MANUFACTURER(manufacturerid)
The last column allows you to associate a variant name (e.g. "HP") with the row where the main manufacturer record is stored (e.g. "Hewlett Packard").
124, Hewlett Packard, 124
367, HP, 124
The row where primarymanufacturerid = manufacturerid is the the main entity.
Then you could do this during an interim cleanup phase when you have not yet added a manufacturerid to the PRODUCTS table but it still has the name:
select * from products
where manufacturer in
(
select manufacturername from manufacturer
where primarymanufacturerid =
(
select primarymanufacturerid from manufacturer
where manufacturername = 'Hewlett Packard'
)
)
P.S. With a database engine that had support for functions and stored procedures, you could write your own function that accepted a delimited string of name variations, built a dynamic SQL statement, possibly using a temporary table to store the variant names one name per row, and returned a count of the matches. This would be a resource-intensive approach recommended only to assist in the clean-up phase -- not something I'd put into production for end-users to consume as their daily bread.
P.P.S. And, of course, once you have your MANUFACTURER table properly created, with the primarymanufacturerid references completed, you could add a [manufacturerid] column to your PRODUCTS table and update it accordingly, and then dispense with all of this roundabout stuff.
$sql = 'SELECT manufacturer FROM shop_articles WHERE 1=1';
for($i=0;$i
by this you can run query for $searchParams array dynamically

seo url`s in php

I have read about "slugs" but I still can`t figure out how to use them. How to properly save slugs in database ?
Lets say i have url like this http:/example.com/samsung/samsung_continuum_android_smartphone /
This is what I do
select category_id from categories where category_name = 'samsung'
After that I do query like
select slugs from my_table where category_id = (lets say 3 where is samsung)
Result is something like
samsung_continuum_android_smartphone
samsung_some_other_phone.
After that I can do something like this
select * from info where title = 'samsung_continuum_android_smartphone'
to get the information about the product. Is this the right way to do it ?
Your going a little over board, slugs are the exact same principle as unique identification numbers, the only difference is that a slug represents natural language for ease of reading as well as SEO.
Now I see that your performing 2 queries to get the row that matches the slug, where as you should only select 1 row from your info where the slug matches the container.
For instance:
SELECT * FROM categories WHERE category_slug = 'samsung';
the category_slug would be just as unique as category_id, thus removing any conflict's that may occur.
now if you construct your table scheme so that the slugs are only uniq to the category, this would remove conflicts but each slug for a post would need to be unique for the category, you can then select the correct post from the post table filtered by the category.
SELECT * FROM posts WHERE category_id = (SELECT category_id FROM categories WHERE category_slug = 'sumsung') AND WHERE post_slug = 'this_would_be_the_slug_for_the_post'
both of these values can be pulled from $_GET and placed into the above SQL String.

Categories