join one row from another table in mysql - mysql

I'm having a problem with a sql query to do the following:
I need to select all products from products table and for each product i need to join a main image (all columns) from images table. Product images table contains image-product relations and a column sortWeight. Main image is the one with the smallest sortWeight.
To get the main product image, i'd do this:
SELECT * FROM images WHERE product=SOME_PRODUCT ORDER BY sortWeight ASC LIMIT 1;
To get all products:
SELECT * FROM products;
Now i need to join these two somehow, but the problem is i don't know how to bypass a limitation in the following:
SELECT P.* FROM products AS P
LEFT JOIN
(SELECT * FROM images AS I WHERE I.product=P.id ORDER BY sortWeight ASC LIMIT 1) AS I1
The problem is MySQL does not know what P.id is inside the subquery. I've also tried it like this:
SELECT P.* FROM products AS P
LEFT JOIN
(SELECT * FROM images AS I WHERE ORDER BY sortWeight ASC LIMIT 1) AS I1 ON (I1.product = P.id)
but i don't think this gives an accurate result since there's a limit in subquery and it may select the image from another product with smaller sortWeight.
Can anyone help me rewrite this? Thank you.

Try to join it to subquery that returns images with smallest (min) sortWeight for each product.
This returns smallest sortWeight for each product:
select product, min(sortWeight) as sortWeight
from images
group by product
this is combined version:
SELECT P.*, i.*
FROM products AS P
left join images as i on p.id = i.product
LEFT JOIN (
select product, min(sortWeight) as sortWeight
from images
group by product
) t on t.product = i.product and i.sortWeight = t.sortWeight

Related

Select limit on foreign key in MySQL

I have two tables. Products and products-sub. I want to show all the available colors for each product and a picture for that too.
So, my product table contains:
id,name,description
My product-sub table contains:
id, parentID, color, pic
I want to select all the colors and the pictures of one product and show it on the page. But I don’t want to show all the products on the same page.
select p.name, s.color, s.pic, p.id
from products-sub s
inner join products as p on p.id = s.parentID
This is my current query, and I want 50 unique s.parentID's.
One solution is to join on the parent table using a subquery with a LIMIT, e.g.
... JOIN (SELECT * FROM products LIMIT 50) p ...
If you want 50 products, then use a subquery:
select p.name, s.color, s.pic, p.id
from products_sub s inner join
(select p.*
from products p
limit 50
) p
on p.id = s.parentID;
This assumes, of course, that all the products have at least one sub.

sql join distinct php

I'm trying to create a list of my products. I got a join between two tables, products and products_photos.
I got X products which have one register on the products photos. The problem comes when I got two register on the product photos table which have the same id_product. Then, the results show 2 times the same product with the different photo. I want to show only the first one, not two times the same product.
SELECT DISTINCT p.*, photo.url_little
FROM ".Constants::$PRODUCTS_TABLE." as p
LEFT JOIN ".Constants::$PHOTOS_PRODUCTS_TABLE." as photo ON p.id=photo.id_product
WHERE p.id_client = ?
Probably I'm doing a bad use of the command distinct, but I don't know how to resolve this.
If you only want to show one, use a correlated subquery:
select p.*,
(select ph.url_little
from ".Constants::$PHOTOS_PRODUCTS_TABLE." ph
where p.id = ph.id_product
order by ph.id asc
limit 1
) as url_little
from ".Constants::$PRODUCTS_TABLE." as p
where p.id_client = ?;
if you use DISCINCT p.* then you obtain all the rows because you select also the row di (and this is unque)
try the same query but only with the column you need
SELECT DISTINCT p.column_i_need1, photo.url_little
FROM ".Constants::$PRODUCTS_TABLE." as p
LEFT JOIN ".Constants::$PHOTOS_PRODUCTS_TABLE." as photo
ON p.id = photo.id_product WHERE p.id_client = ?

Select top 10 posts ordered by quantity of votes

I have two tables, one for image records (posts) and the other one is for likes records. So i made an INNER JOIN from one table to another because i needed to select the image and the quantity of likes that particular image has. but i also need to order them by the quantity of likes so i can make a top 10 of most voted images on the site, so here is my query:
SELECT
COUNT(DISTINCT B.votes),
A.id_image,
A.image,
A.title
FROM likes_images AS B INNER JOIN images AS A ON A.id_image = B.id_image
GROUP BY A.title
ORDER BY COUNT(DISTINCT B.votes) ASC
LIMIT 10
It works, but it's only ordering the images by the title (Alphabetical). I want to order them from the most voted to the less voted.
Any ideas?
In most SQL implementations, GROUP BY criterion implies any ORDER BY clause to be ignored in favor of criterion.
So you might try this:
SELECT L.id_image, A.image, A.title,
* FROM (
SELECT COUNT(votes) AS likes, id_image
FROM likes_images
GROUP BY id_image
) AS L
JOIN images B ON B.id_image = L.id_image
ORDER BY L.likes DESC
LIMIT 10
Note that I set ORDER BY to DESC (since you want top10 I don't understand you chose ASC)!

mysql left join not returning empty row

I'm trying to get the list of categories with number of child records present in there. If the categories doesn't have records it should return NULL or 0 but my query returning categories with child records looks like its skipping the one without child records. ... will really appreciate the help.
here's my code:
SELECT
t_gal.f_sub_category_id,
t_sub_cat.f_sub_cat_name,
t_gal.f_image_thumb, (
SELECT COUNT(*)
FROM t_gallery
WHERE f_sub_category_id = t_gal.f_sub_category_id)
AS f_image_total
FROM t_gallery t_gal
LEFT JOIN t_sub_category t_sub_cat ON t_sub_cat.r_id = t_gal.f_sub_category_id
GROUP BY t_sub_cat.r_id
ORDER BY t_gal.f_added_on DESC, t_gal.r_id DESC
Here's the two tables:
Problem appears to be your group by clause.
You are grouping by a field that is on the LEFT JOINed table, hence when it does the group by all the rows which do not have a matching row on that table would appear to be aggregated into a single row.
I think what you are trying to get is a list of gallery items, along with the category they are in (if found) and the count of other galleries in the same category. If so try the following (if not let me know!)
SELECT t_gal.f_sub_category_id, t_sub_cat.f_sub_cat_name, t_gal.f_image_thumb, Sub1.GalleryCount
FROM t_gallery t_gal
LEFT JOIN t_sub_category t_sub_cat
ON t_sub_cat.r_id = t_gal.f_sub_category_id
LEFT OUTER JOIN (SELECT f_sub_category_id, COUNT(*) AS GalleryCount FROM t_gallery GROUP BY f_sub_category_id) Sub1
ON Sub1.f_sub_category_id = t_gal.f_sub_category_id
ORDER BY t_gal.f_added_on DESC, t_gal.r_id DESC
It LOOKS like for every sub-category (of a previously selected category), you want to include ALL of that sub-category... And, of those sub-categories, you want a count of how many images for that category wheather or not there even IS an image in the gallery table.
What you may have been running into is the select statement for the FIELD used to count images... first, that could become a performance killer. Instead, you could just do a left-join directly to the gallery table and COUNT the distinct R_IDs from the gallery FOR the corresponding sub-category
SELECT
t_sub_cat.r_id,
t_sub_cat.f_sub_cat_name,
MIN( COALESCE( t_gal.f_image_thumb, '' )) as JustOneThumbImg,
COUNT( DISTINCT( t_gal.r_id )) SubCategoryImageCount
FROM
t_sub_category t_sub_cat
LEFT JOIN t_gallery t_gal
ON t_sub_cat.r_id = t_gal.f_sub_category_id
GROUP BY
t_sub_cat.r_id
ORDER BY
t_sub_cat.f_added_on DESC
Since you are not grabbing all gallery images (since some may not exist FOR a given sub-category), ordering by the t_gal.r_id doesn't make sense
Also, the reason I'm not pre-grabbing aggregates in a sub-query to join against... I don't want to get everything from every category / sub-category without knowing which sub-categories are associated with the category you actually want.
the problem with your query is that you are using t_gallery as your main table and not t_sub_category while using left join.
you could try this: sqlfiddle
select
t_gal.f_sub_category_id,
t_sub_cat.f_sub_cat_name,
(
SELECT COUNT(*)
FROM t_gallery
WHERE f_sub_category_id = t_gal.f_sub_category_id)
AS f_image_total
from t_sub_category as t_sub_cat
left join t_gallery t_gal on t_gal.f_sub_category_id = t_sub_cat.r_id
GROUP BY t_sub_cat.r_id
ORDER BY t_gal.r_id DESC;

MySQL join or subquery - get product data along with first product image

I'd like to be able to return a thumbnail (first image of a set) with my product data - what is the best way to accomplish this (performance)?
I have the following tables:
products (product data)
products_images (relation between products and images)
images (image data)
So for every product, it'd return the first image of a set associated with that product.
Two things:
I'm trying to get the first image but the order depends on an 'order'
field.
If no image found just return null for image data but still
get product.
I'm thinking of doing a subquery since I don't know how to about ordering and limiting image results in a join.
What do you suggest?
Edit:
The image order field is present in the products_images table. That table has the following fields (product_id, image_id, order)
SELECT
p.*
, i.thumbnail
FROM
products AS p
LEFT JOIN
images AS i
ON i.image_id =
( SELECT image_id
FROM products_images AS pi
WHERE pi.product_id = p.product_id
ORDER BY `order` ASC --- or DESC
LIMIT 1
)
An index on (product_id, order, image_id) in table products_images would be useful for the subquery to run faster.
This should give you the first image by the order column in the product_images table:
SELECT *
FROM products p
LEFT JOIN (
SELECT pi.product_id, i.*
FROM images i
INNER JOIN (
SELECT product_id, image_id
FROM products_images pi
ORDER BY `order`
) pi ON i.image_id = i.id
GROUP BY product_id
) i ON i.product_id = p.id