I'm trying to query my database for all my products and when I do that it's crashing the server and I can't get the information
SELECT categories.category_id,
categories.category_name,
categories.category_name_fr,
subcategories.subcategory_id,
subcategories.subcategory_name,
subcategories.subcategory_name_fr,
suppliers.supplier_id,
suppliers.supplier_name,
products.product_id,
products.product_name,
products.product_name_fr,
products.product_url
FROM categories,
subcategories,
suppliers,
products
WHERE products.product_active = 1
ORDER BY categories.category_id ASC
I tried putting a LIMIT 0, 1 and it STILL crashed...
First, you should explicitly specify your joins and join conditions, as right now you are getting a Cartesian product of all the tables, which is likely not what you want.
You should list the products table first amongst the joined tables, as this is the table where your WHERE clause filtering is in effect. So something like:
SELECT categories.category_id, categories.category_name,
categories.category_name_fr, subcategories.subcategory_id,
subcategories.subcategory_name, subcategories.subcategory_name_fr,
suppliers.supplier_id, suppliers.supplier_name, products.product_id,
products.product_name, products.product_name_fr, products.product_url
FROM products
INNER JOIN categories ON products.[some field] = categories.[some field]
INNER JOIN subcategories ON categories.[some field] = subcategories.[some field]
INNER JOIN suppliers ON products.[some field] = suppliers.[some field]
WHERE products.product_active = 1
ORDER BY categories.category_id ASC
Second, you need to make sure you have an index on each of products.product_active and categories.category_id as well as any other columns used in the join conditions.
Third, just as an FYI, a LIMIT condition would do nothing to help the query execution time here as you still need to perform the join, the filter, and the sort before deciding to limit the result set to just a subset of the items. The only place where it would help would be in processing through the result set (which would obviously happen much quicker).
Related
First, I have my database like this:
And the relations:
And now in the .php I want to create the table that shows everything in the table but instead of showing ProductId and UpgradeProductId as a number, I want to show them as name of the product
The problem is how can I do it? I already made this
And it show up like this
I want the [UpgradeProductId] to come out as Product Name like [ProductId] but I don't know how to write it to connect the SQL and have a result.
I hope I understood your question correctly.
The easy way to display the ProductName for your UpgradeProductId would be a SELECT statement for the column.
The statement would look like that:
SELECT UpgradeId, Productname, (SELECT Product.ProductName FROM Product WHERE Product.ProductId = Upgrade.UpgradeProductId), UpgradeDate, UpgradeDetail
FROM Upgrade
INNER JOIN Product ON Upgrade.ProductId = Product.ProductId
INNER JOIN RepairMan ON Upgrade.RepairManId = RepairMan.RepairManId
WHERE Upgrade.RepairManId = '$RepairManId'
ORDER BY UpgradeId ASC
However I guess, that this is not the most efficient solution.
To do the same with joins, you have to use aliases for your joined tables. It would look like this:
SELECT UpgradeId, P1.Productname, P2.Productname, UpgradeDate, UpgradeDetail
FROM Upgrade
INNER JOIN Product AS P1 ON Upgrade.ProductId = P1.ProductId
INNER JOIN Product AS P2 ON Upgrade.UpgradeProductId = P2.ProductId
INNER JOIN RepairMan ON Upgrade.RepairManId = RepairMan.RepairManId
WHERE Upgrade.RepairManId = '$RepairManId'
ORDER BY UpgradeId ASC
Another thing besides that. I don't know exactly which SQL you are using, but be sure to add either ASC or DESC to your ORDER command. Without this addition, some types of SQL tend to not order as you intended.
I've seen many questions like mine, but after reading them all I got rather confused.
To sum up - I've got a query that select products from a table and adds more information about them from other tables.
Query:
SELECT
p.product_id,
p.product_name,
p.product_seo_url,
p.product_second_name,
p.product_intro_plain,
p.product_price,
p.product_price_promo,
p.product_promo_expire_date,
p.product_views,
p.product_code,
p.product_exquisite,
p.product_rating,
p.product_votes,
p.product_date_added,
p.product_returned,
p.product_price_returned,
( SELECT gal.image_filelocation
FROM 3w_products_gallery gal
WHERE gal.product_id = p.product_id
ORDER BY show_order ASC
LIMIT 1 ) image_filelocation,
m.man_image_location,
m.man_name,
m.man_seo_url
FROM
3w_products p
LEFT JOIN 3w_manufacturers m
ON p.man_id = m.man_id
LEFT JOIN 3w_products_cat_rel pcr
ON p.product_id = pcr.product_id
WHERE
pcr.ctg_id = '19'
AND p.man_id = '190'
ORDER BY
p.product_id DESC
LIMIT
0, 24
The strange things that happen are that the query sometimes executes for 0.001 sec. and sometimes for 30+ seconds.
There is what EXPLAIN shows:
http://i.stack.imgur.com/ZNtBX.png
I assume the problem lies in the indexes of the tables. Can you tell me how to setup them?
Let me know if you need any more information about the tables or whatever!
Best,
Dimitar
IF your "ID" columns are actually numeric, remove the quotes around them implying strings... even though it would to an implied conversion. If numeric, keep it numeric.
As stated by another in the comments, your LEFT JOIN via the "pcr" alias with its criteria in the WHERE clause turns this into an inner join.
FROM
3w_products p
LEFT JOIN 3w_manufacturers m
ON p.man_id = m.man_id
LEFT JOIN 3w_products_cat_rel pcr
ON p.product_id = pcr.product_id
AND pcr.ctg_id = 19
WHERE
AND p.man_id = 190
Field-level queries can kill performance since the select for each field (your image location) is done once for every record. To at least help this performance, table 3w_products_gallery should have an index ON ( product_id, show_order )
Your main 3w_products table should have an index on (man_id, product_id )... The Man_ID to optimize the WHERE clause by manufacturer, but also the product ID to help optimize the ORDER BY criteria.
Your 3w_manufacturers table, I would suspect already has a valid index on (man_id), since it appears to be the primary key to the table.
Additionally, being web-based content, you might be better to DE-NORMALIZE your product table by adding one new column for "GalleryShowOrder". Then, add a trigger to your Gallery table that any insert or update will then push the first "showOrder" value back to the product table. This way, when you query, you can just add another join to that table on the product and KNOWN show order. If your gallery is returning 1000's of records, even though you are only limiting to 24, it still needs to get all record before the order by is applied. Thus 1000's of subqueries for each of the gallery images.
and your field selection would just become
gal.image_filelocation,
and your JOIN would add the following
LEFT JOIN 3w_products_gallery gal
on p.product_id = gal.product_id
AND p.GalleryShowOrder = gal.show_order
I have product details in tne table, say products, categories and brand names in different tables say categories and brand. And I want to join these in a query. The query I use is,
$sql = "
SELECT p.pid
, p.name
, p.slug
, p.category
, c.name
, p.brand
, b.name
FROM products p
JOIN categories c
ON c.sno = p.category
JOIN brand
ON b.sno = p.brand
WHERE p.sku=?
";
This query does not return any rows. However there are data in products, categories and brand tables.
Is there any logic failure in my query?
Products table
Categories table
Brand table
This is a bit long for a comment.
For the data that you have shown, your query should work. I would start by removing the where clause and running:
SELECT products.pid, products.name, products.slug, products.category, categories.name, products.brand, brand.name
FROM `products`
INNER JOIN `categories` on products.category = categories.sno
INNER JOIN `brand` on products.brand = brand.sno ;
(You should run this directly on the database; if there is a lot of data, just throw in a limit 100 to see if you get anything.)
If this doesn't return anything, then you have a problem with the joins. Look at the types of the fields. Are they the same? If not, fix the data structure. If they are characters, check for leading spaces and hidden characters.
If that query returns what you expect, the the problem is matching the skus. The most likely problem is the assignment of the value in php. Check that this is really doing what you want. Once again, check for leading spaces in the sku column and in the value. If this is the problem, you can use trim() to fix the problem.
I have four tables:
users, orders, orders_product and products.
They are connected to each other by foreign key
user tables contains: id, name, email and username.
product table contains: id, product_name, product_description and product_price
orders table contains: id, u_id(foreign key).
orders_product table contains: id, product_id(foreign key), order_id(foreign key).
Now I was trying to fetch the name of a user with the total price of a particular order that he has placed.
The maximum I could went for was something like this:
SELECT prod.order_id,
SUM(product_price) AS Total
FROM products
INNER JOIN
(SELECT orders.id AS order_id,
orders_product.product_id
FROM orders
INNER JOIN orders_product ON orders.id = orders_product.order_id
WHERE order_id=1) AS prod ON products.id = prod.product_id;
It showed me total price of a particular order. Now I have two questions:
Is that query correct. It looks like a very long query. Can the same result be achieved with a smaller one?
How to fetch the name of a user with the total price of a particular order that he has placed.
Hi some addition to #Gordon Linoff
your query seems ok.
if you store your price data in order_products it will be good and some benefit, one of these benefit is aggregation will be simple. Second benefit if product price change it will not affect to order.
Your query is correct for one order, but it can be improved:
Don't use a subquery unless necessary. In MySQL this introduces additional overhead.
You are only looking at one order, which seems on the light site. You should remove the where clause.
You should be using a group by because you want aggregation.
You need to join in the user table to get the name.
I also added table aliases (abbreviations for table names). This makes the query a bit more readable:
SELECT u.name, SUM(p.product_price) as Total
FROM orders_product op INNER JOIN
orders o
ON o.id = op.order_id INNER JOIN
products p
ON p.id = op.product_id INNER JOIN
users u
on o.userid = u.id
WHERE op.order_id = 1
GROUP BY u.name;
Your SQL is wrong. Because You want to calculate specific to user. But your SQL is specific to Order. Your SQL will give result for One Order. Please make it User Specific by giving user name or what ever is unique.
I've been racking my brain for hours trying work out how to join these two queries..
My goal is to return multiple venue rows (from venues) based on certain criteria... which is what my current query does....
SELECT venues.id AS ven_id,
venues.venue_name,
venues.sub_category_id,
venues.score,
venues.lat,
venues.lng,
venues.short_description,
sub_categories.id,
sub_categories.sub_cat_name,
sub_categories.category_id,
categories.id,
categories.category_name,
((ACOS( SIN(51.44*PI()/180)*SIN(lat*PI()/180) + COS(51.44*PI()/180)*COS(lat*PI()/180)*COS((-2.60796 - lng)*PI()/180)) * 180/PI())*60 * 1.1515) AS dist
FROM venues,
sub_categories,
categories
WHERE
venues.sub_category_id = sub_categories.id
AND sub_categories.category_id = categories.id
HAVING
dist < 5
ORDER BY score DESC
LIMIT 0, 100
However, I need to include another field in this query (thumbnail), which comes from another table (venue_images). The idea is to extract one image row based on which venue it's related to and it's order. Only one image needs to be extracted however. So LIMIT 1.
I basically need to insert this query:
SELECT
venue_images.thumb_image_filename,
venue_images.image_venue_id,
venue_images.image_order
FROM venue_images
WHERE venue_images.image_venue_id = ven_id //id from above query
ORDER BY venue_images.image_order
LIMIT 1
Into my first query, and label this new field as "thumbnail".
Any help would really be appreciated. Thanks!
First of all, you could write the first query using INNER JOIN:
SELECT
...
FROM
venues INNER JOIN sub_categories ON venues.sub_category_id = sub_categories.id
INNER JOIN categories ON sub_categories.category_id = categories.id
HAVING
...
the result should be identical, but i like this one more.
What I'd like to do next is to JOIN a subquery, something like this:
...
INNER JOIN (SELECT ... FROM venue_images
WHERE venue_images.image_venue_id = ven_id //id from above query
ORDER BY venue_images.image_order
LIMIT 1) first_image
but unfortunately this subquery can't see ven_id because it is evaluated first, before the outer query (I think it's a limitation of MySql), so we can't use that and we have to find another solution. And since you are using LIMIT 1, it's not easy to rewrite the condition you need using just JOINS.
It would be easier if MySql provided a FIRST() aggregate function, but since it doesn't, we have to simulate it, see for example this question: How to fetch the first and last record of a grouped record in a MySQL query with aggregate functions?
So using this trick, you can write a query that extracts first image_id for every image_venue_id:
SELECT
image_venue_id,
SUBSTRING_INDEX(
GROUP_CONCAT(image_id order by venue_images.image_order),',',1) as first_image_id
FROM venue_images
GROUP BY image_venue_id
and this query could be integrated in your query above:
SELECT
...
FROM
venues INNER JOIN sub_categories ON venues.sub_category_id = sub_categories.id
INNER JOIN categories ON sub_categories.category_id = categories.id
INNER JOIN (the query above) first_image on first_image.image_venue_id = venues.id
INNER JOIN venue_images on first_image.first_image_id = venue_images.image_id
HAVING
...
I also added one more JOIN, to join the first image id with the actual image. I couldn't check your query but the idea is to procede like this.
Since the query is now becoming more complicated and difficult to mantain, i think it would be better to create a view that extracts the first image for every venue, and then join just the view in your query. This is just an idea. Let me know if it works or if you need any help!
I'm not too sure about your data but a JOIN with the thumbnails table and a group by on your large query would probably work.
GROUP BY venues.id