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.
Related
I have a query: SELECT brand FROM products WHERE brand='".$brand."' AND category='".$id."'".$categories_list."
The idea is to get a count of the total products within a category or across multiple categories by a category ID or IDs by a brand number.
The code as it sits:
foreach ($product_brands as $brand) {
$products_sql = mysqli_query($mysql_link, "SELECT brand FROM products WHERE brand='".$brand."' AND category='".$id."'".$categories_list."");
$brand_total = #mysqli_num_rows($products_sql);
array_push ($product_brands_count, $brand_total);
}
It works correctly when only counting a single category. However, it displays incorrect counts when trying to count multiple categories.
The $categories_list adds OR category='".$categories_data['id']."' to the query if there are multiple categories shown.
I've tried to move the brand='".$brand."' around in the query statement, but that hasn't worked for me.
Here are some of the counts I get.
Single category: -- which is correct
Brand 1 = 3
Brand 2 = 5
Multiple Categories -- which is not
Brand 1 = 8
Brand 2 = 11
Your primary problem is a logical prescedence issue. You are generating a where clause like:
WHERE brand = ? AND category = ? OR category = ?
Since AND has higher prescendence than AND, this actually means:
WHERE (brand = ? AND category = ?) OR category = ?
This accepts rows whose category matches the second category parameter, regardless of their brand.
You need parentheses to control the prescendence:
WHERE brand = ? AND (category = ? OR category = ?)
This can be shortened with IN:
WHERE brand = ? AND category IN (?, ?)
But bottom line, I don't see the point for looping over the brands in php, fetching all rows and then counting them. Your database can manage sets of rows much more efficiently with an aggregation query.
Something like this should be close to what you need:
select brand, count(*) no_products
from products
group by brand
where category in (?, ?)
Note that all above queries are parameterized (ie the parameters are not concatenated in the query string, but passed to the query at execute time instead). You do want to use this technique to make your code more efficient and prevent SQL injection.
Let's say we have a table with 4 columns: id (int 11, indexed), title, content, category (varchar 5).
I have a user select a category. Each category can contain up to 999 objects. Using SELECT id FROM table WHERE category = ? I get a list of all objects.
I then have the user select/deselect some of the objects. After which I need to select the content of the remaining selected objects.
Now my question is as follows, should I worry about performance when using SELECT content FROM table WHERE id IN($array)? Would it be better to use SELECT content FROM table WHERE category = ? AND id IN($array). The idea here being I filter it down to 999 objects before performing the IN...
Does this make any sense? Or should I not be using the IN() at all?
It sounds like you always have content showing on the screen?
999 is a long list to put on the screen. Re-think your UI.
When selected/deselected, what happens? Do you gray out the content? If so, that is a UI issue, not a database issue. If you store the subset that is currently "selected", then how/where is that stored? And, do you want to store it after each select/deselect? Or wait until he clicks "Submit"?
In other words, I don't see why this is a database question.
Back to the queries in question:
INDEX(category)
SELECT ... FROM tbl WHERE category = ...; -- This is optimal
PRIMARY KEY(id)
SELECT ... FROM tbl WHERE id IN (...); -- optimal for an arbitrary set
INDEX(category, id)
SELECT ... FROM tbl WHERE category = ... AND id IN (...)
-- use this only if you both parts are needed for filtering
-- not for optimizing
I Made two tables
posts
categories
In posts table I created category column, here I store multiple category_id like this 1,2,3.
The problem is if category column has single category_id like 1 or 2 or 3, I can easily query the data like this:
SELECT title FROM posts WHERE category = $category_id
However, I am unsure as to how to query the comma-delimited data. Is there a way to do this, or should I change the table structure ?
Here you can have:
Categoryid: 1
Postid: 1,2,3
Result = Categoryid: 1 --> Postid 1,2,3
You could either create a junction table (probably with an EAV design) or keep your unique table and use FIND_IN_SET, as such :
SELECT title FROM posts WHERE FIND_IN_SET(1, category) > 0
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,%"
in my sphinx source config I have an attribute like so:
sql_attr_multi = uint categories from query; SELECT entry_id, cat_id FROM categories_entries
When querying the sphinx index, is it possible to get only records that do not have a category attribute? As a kludgy fix I have executed a query on the database to find all potential category ids and then excluded those attributes from the Sphinx results:
$query = $DB->query("SELECT GROUP_CONCAT(cat_id SEPARATOR ',') AS categories
FROM categories WHERE category_group='3'
GROUP BY category_group");
$sphinxclient->SetFilter("categories", explode(",", $query->result[0]['categories']), true);
This works but it seems like there should be a better way.
There's no way to check if an MVA collection is empty for a given document... however, you could add another integer attribute which is the COUNT for categories attached to each document. Then you can filter on that equalling zero, or being within a certain range.