We have six categories Example :- a,b,c,d,e,f.
In each category we have products.
In a category i have 2 products & in b category i have 1 product.
I'm fetching this data from database.
product_id category_id
1 1
2 1
3 2
What should be best logic to display records, so two categories not display next to it.
Output product id like :- 1,3,2
I do not think such function exists. Even if you use DISTINCT it will only select the ones that do not duplicate and leave the out the rest, which is not what you need. So, I think I would run two queries at the same time, the first one will choose all the distinct queries, like 1,2,3,4 and after that, you can create a second query just to query normally all products. This way, let say.. if you had products by type like 1,1,2,3,3,3,4,4,4,4,5,5,5, then, the first sql query would list 1,2,3,4,5 and the second will just query normally, but still, your clients will see the distinct ones first.
SELECT DISTINCT type FROM table ORDER by id
Related
SELECT name, price, photo FROM drinks, drinks_photos WHERE drinks.id = drinks_id
yeilds 5 rows (5 arrays), photo is the only unique field in a row. name, price get repeated (here, fanta- name, price repeat 3 times.) How do i get rid of these duplicates?
Edit: I want name, price and all photo for each drink.
id name price
1. fanta 5
2. dew 4
id photo drinks_id
1. ./images/fanta-1.jpg 1
2. ./images/fanta-2.jpg 1
3. ./images/fanta-3.jpg 1
4. ./images/dew-1.jpg 2
5. ./images/dew-2.jpg 2
What you do here is called a JOIN (although you do it implicitly because you select from multiple tables). This means, if you didn't put any conditions in your WHERE clause, you had all combinations of those tables. Only with your condition you restrict your join to those rows where the drink id matches.
But there are still X multiple rows in the result for every drink, if there are X photos with this particular drinks_id. Your statement doesn't restrict which photo(s) you want to have!
If you only want one row per drink, you have to tell SQL what you want to do if there are multiple rows with a particular drinks_id. For this you need grouping and an aggregate function. You tell SQL which entries you want to group together (for example all equal drinks_ids) and in the SELECT, you have to tell which of the distinct entries for each grouped result row should be taken. For numbers, this can be average, minimum, maximum (to name some).
In your case, I can't see the sense to query the photos for drinks if you only want one row. You probably thought you could have an array of photos in your result for each drink, but SQL can't do this. If you only want any photo and you don't care which you'll get, just group by the drinks_id (in order to get only one row per drink):
SELECT name, price, photo
FROM drinks, drinks_photos
WHERE drinks.id = drinks_id
GROUP BY drinks_id
name price photo
fanta 5 ./images/fanta-1.jpg
dew 4 ./images/dew-1.jpg
In MySQL, we also have GROUP_CONCAT, if you want the file names to be concatenated to one single string:
SELECT name, price, GROUP_CONCAT(photo, ',')
FROM drinks, drinks_photos
WHERE drinks.id = drinks_id
GROUP BY drinks_id
name price photo
fanta 5 ./images/fanta-1.jpg,./images/fanta-2.jpg,./images/fanta-3.jpg
dew 4 ./images/dew-1.jpg,./images/dew-2.jpg
However, this can get dangerous if you have , within the field values, since most likely you want to split this again on the client side. It is also not a standard SQL aggregate function.
You will have the duplicate values for name and price here. And ids are duplicate in the drinks_photos table.There is no way you can avoid them.Also what exactly you want the output ?
In order to get rid of duplicates, you can group by drinks.id. But that way you'll get only one photo for each drinks.id (which photo you'll get depends on database internal implementation).
Though it is not documented, in case of MySQL, you'll get the photo with lowest id (in my experience I've never seen other behavior).
SELECT name, price, photo
FROM drinks, drinks_photos
WHERE drinks.id = drinks_id
GROUP BY drinks.id
As I do not know anything about speed and complexity of php and mysql(i) scripts, I had this question:
I have a database with 3 tables:
'Products' with about 9 fields. Containing data of products, like 'long' content text.
'Categories' with 2 fields. Containing name of categories
'Productcategories' with 2 fields. Containing which product has which categories. Each product is part of 1-3 categories.
In order to set up pagination (I need row_count because I wish to know what the last page is), I was wondering what the most sufficient way to do it is, and or it depends on the amount of products (50, 100, 500?). The results returned depends on a chosen category:
"SELECT * FROM `productcategories`
JOIN products ON products.proID = productcategories.proID
WHERE productcategories.catID =$category";
Idea 1:
1 query which only selects 1 field, instead of all. And then counts the total rows for my pagination with mysqli_num_rows().
A second query which directly selects 5 or 10 (with LIMIT I expect) products to be actually shown.
Idea 2:
Only 1 query (above), on which you use mysqli_nuw_rows() for row count and later on, filter out the rows you want to show.
I do not know which is the best. Idea 1 seems faster as you have to select a lot less data, but I do not know or the 2 queries needed influence the speed a lot? Which is the fastest: collecting 'big' amounts of data or doing queries?
Feel free to correct me if I am completely on the wrong path with my ideas.
It is generally considered best practice to return as little data as possible so the short answer is to use the two queries.
However, MySQL does provide one interesting function that will allow you to return the row count that would have been returned without the limit clause:
FOUND_ROWS()
Just keep in mind not all dbms' implement this, so use with care.
Example:
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
-> WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();
Use select count(1) as count... for the total number of rows. Then select data as needed for pagination with limit 0,10 or something like that.
Also for total count you don't need to join to the products or categories tables as that would only be used for displaying extra info.
"SELECT count(1) as count FROM `productcategories` WHERE catID=$category";
Then for data:
"SELECT * FROM `productcategories`
JOIN categories ON categories.catID = productcategories.catID
JOIN products ON products.proID = productcategories.proID
WHERE productcategories.catID=$category limit 0,10";
Replacing * with actual fields needed would be better though.
What is the best practice to do a searching form with filters, where the filters are depending on the category?
e.g.:If you go to visit the ebay and select a category then the filters are different on the left hand side in the cell phones (filters: brand, operating system...) or the fashion category (filters: size, color...)...
In my mind I would do more table in DB. Each table for one category (cat_cellphone, cat_fashion...). Then put a product one of these tables depending on the category (not one products table where one column contains the category ID).
These tables are different where the columns names are characterized by the category.
Next, should do more searching forms and call a form where the filter belongs to the category.
Is it a good concept or there is an other accepted practice in big projects?
No, having multiple tables is a bad idea.
In general. use a table with a primary key over two columns instead.
(The primary key may span more than one column.)
The columns would be categoryname / filtername.
If you don't like such primary keys, and always use an autoincrement column, you can still create an index over the two columns.
The columns would be: id / categoryname / filtername / filtertext
Using multiple tables to store your products isn't a good idea. Because there will be products that overlap in categories which would result storing the same product in more than one table.
Just use a product table with the ID, product_number, description, etc. and a category table to store the different categories. Then you could link them directly like:
Product table:
ID product_number description category
1 00001 Screwdriver 1
Category table:
ID description
1 Tools
And you could even expand the category table with an extra column to use subcategories by addressing the parent of the subcategory:
Category table with subcategories:
ID description parent
1 Tools NULL
2 Automatic tools 1
And if you don't like directly linking to the category table from the product table you could use a link table:
Product_category:
Product_ID Category_ID
1 1
Hope this answers your question.
Edit, added filter table:
To add filtering for a product you can use a table for a the filters and a link table, like so:
Filter:
Filter_ID description value
1 brand Bosch
2 brand Bahco
3 type Phillips
Product_Filter:
Product_ID Filter_ID
1 1
1 3
That way you can link more than one filter to each product and use the same filter more than once.
You could even expand this further by using another table for the filter values, but that could make things a bit to complicated:
Filter:
Filter_ID description value
1 brand 1
Filter_value:
Filter_ID value
1 Bosch
2 Bahco
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
I am trying to fetch data from multiple tables depending on what is selected in a dropdown menu. My dropdown menu consists of a list of ID's (001, 002, etc).
Once a user selects one of them, I am using AJAX to dynamically fetch data depending on what was selected. I was able to fetch a single value depending on what was selected but having problems when multiple tables are involved.
My tables are set up like this:
Inventory table:
inven_ID (primary)
cost
description
Order table:
order_ID(primary)
orderdesc
Sale table:
inven_ID
order_ID
quantity
primary(inven_ID,order_ID)
My query is as follows:
$QRY = "SELECT
inven_ID,
order_ID,
cost,
description
FROM
Inventory,
Order,
Sale
WHERE Inventory.inven_ID = Sale.inven_id
AND Sale.order_ID = Order.order_ID
AND Order.order_ID ='".$q."'";
The $q represents the value from the dropdown menu (which I checked is valid). I am getting the error Column 'inven_ID' in field list is ambiguous. Basically, when they select some order id from the drop down (say 001), it looks for order_ID in my Order table, and fetches the inven_ID/cost/description of that particular order ID.
Eg. if someone ordered parts xy, yz, xyz for cost 10,20,30.
Selecting 001 would bring up:
001 xy 10
001 yz 20
001 xyz 30
I think I am not joining tables properly since the error says its ambiguous.
Any help on this?
edit: yes that fixed the problem, quite obvious that I did not catch it.
In the column list of your select, you just need to specify which inven_ID you want to retrieve. For instance:
SELECT Inventory.inven_ID, ...
The error is pretty obvious. inven_ID is ambiguous because you have it in Sale and in Inventory. Use a specifier like Sale.inven_ID or Inventory.inven_ID.