how to do inner join on the first row of the table - mysql

I have the following query:
SELECT p.`id` , p.`name` , pp.`name`
FROM `product` p
INNER JOIN `product_picture` pp ON p.id = pp.product_id
and then this gives me the following result:
However I only wanted to get only one product picture for each item (which is the first one on top). So I wanted to get a query that returns:
7 Glavins Necklace 83081c5619068f6ec700e12d827d2199745c8283.jpeg
8 Woodsie Bracelet 83081c5619068f6ec700e12d827d2199745c8283.jpeg
How do I do so?

Use an aggregate MIN() or MAX() to pick one picture
SELECT p.`id` , p.`name` , MIN(pp.`name`) picture
FROM `product` p INNER JOIN `product_picture` pp
ON p.id = pp.product_id
GROUP BY p.`id` , p.`name`

Related

How to get only distinct values based on one column from different tables - SQL?

I have a MySQL database that I imported to Google Data Studio, and I have made the following query to get the data from multiple tables:
SELECT sw.waybill_number, sw.order_id as sworder_id, sw.status, sw.cod, sw.id AS sw_id, sw.created_at as sw_ca, c.shipping_price, c.id as c_id, oi.id as oi_id, oi.created_at as oi_ca, oi.order_id as oiorder_id, oi.product_id as oip_id, p.created_at as p_ca, p.id as p_id, p.name
FROM shipping_waybills sw
JOIN cities c
ON sw.state = c.name_en
LEFT JOIN order_items oi
ON sw.order_id = oi.order_id
LEFT JOIN products p
ON oi.product_id = p.id;
However, there are multiple values related to the column i want (sw.waybill_number), but I only want one value, it doesn't matter which one.
How can I do that??
Since you don't care which values are on each sw.waybill_number...
SELECT sw.waybill_number
, MIN(sw.order_id) as sworder_id
, MIN(sw.status) as status
, MIN(sw.cod) as cod
, MIN(sw.id) AS sw_id
, MIN(sw.created_at) as sw_ca
, MIN(c.shipping_price) as shipping_price
, MIN(c.id) as c_id
, MIN(oi.id) as oi_id
, MIN(oi.created_at) as oi_ca
, MIN(oi.order_id) as oiorder_id
, MIN(oi.product_id) as oip_id
, MIN(p.created_at) as p_ca
, MIN(p.id) as p_id
, MIN(p.name) as name
FROM shipping_waybills sw
INNER JOIN cities c ON sw.state = c.name_en
LEFT OUTER JOIN order_items oi ON sw.order_id = oi.order_id
LEFT OUTER JOIN products p ON oi.product_id = p.id
GROUP BY sw.waybill_number

GROUP BY and ORDER BY issues

I have the following query:
SELECT DISTINCT (
s.styleTitle
), COUNT(p.id) AS `PictureCount`
FROM `style` s
LEFT JOIN `instagram_picture_style` ps ON s.id = ps.style_id
LEFT JOIN `instagram_shop_picture` p ON ps.picture_id = p.id
LEFT JOIN `instagram_picture_category` c ON c.picture_id = p.id
LEFT JOIN `instagram_second_level_category` sl ON c.second_level_category_id = sl.id
WHERE sl.id =25
GROUP BY p.id
ORDER BY PictureCount
however this query gives me:
I basically wanted the list to be ordered by the style that has the most pictures in it. What did I do wrong? Why is it giving me 1 on all of the styles, I am pretty sure it has more pictures for that style
ORDER BY doesn't have underscores. But equally important, you are using DISTINCT in a way where you seem to think that it is a function. It is not. It is a modifies on the SELECT and it applies to all columns.
You should group by the same column you have in the distinct. Something like this:
SELECT s.styleTitle, COUNT(p.id) AS `PictureCount`
FROM `style` s
LEFT JOIN `instagram_picture_style` ps ON s.id = ps.style_id
LEFT JOIN `instagram_shop_picture` p ON ps.picture_id = p.id
LEFT JOIN `instagram_picture_category` c ON c.picture_id = p.id
LEFT JOIN `instagram_second_level_category` sl ON c.second_level_category_id = sl.id
WHERE sl.id = 25
GROUP BY s.styleTitle
ORDER BY PictureCount DESC;
In fact, you almost never need distinct with group by. If you are using, you need to think why it would be necessary.

MySQL search query INNER JOIN limit id_image field results to 1 per id_product

I'm making a search function for a webshop and to display the results I'm trying to create a SQL query on multiple tables. This query is working:
SELECT ps_product_lang.id_product , ps_product_lang.name as product_name ,
ps_product_lang.description_short,
ps_product_lang.link_rewrite as product_link_rewrite ,
ps_product_lang.meta_title , ps_product.reference ,
ps_product.id_category_default , ps_product.on_sale , ps_product.price ,
ps_category_lang.name as category_name ,
ps_category_lang.link_rewrite as category_link_rewrite , ps_image.id_image
FROM ps_product_lang
INNER JOIN ps_product
INNER JOIN ps_category_lang
ON ps_product.id_category_default=ps_category_lang.id_category
INNER JOIN ps_image
ON ps_product_lang.id_product=ps_image.id_product
WHERE ps_product_lang.name LIKE '%simone%' OR
ps_product.reference LIKE '%simone%' ORDER BY ps_product_lang.id_product ASC
In the search results I want to display only one image. But with this query above I get all the id_images by the desired id_product. I tried different ways to limit it like:
ON ps_product_lang.id_product=ps_image.id_product = (SELECT id_image FROM ps_image LIMIT 1)
But whatever I try, I get no results anymore or I have an error in my syntax. Who can give me a push in the right direction?
If you just want one image per product, use a simple sub select to get one image id, the maximum image id for instance. That means: Remove the join of ps_image completely.
SELECT
ps_product_lang.id_product , ...
ps_category_lang.link_rewrite as category_link_rewrite ,
(
select max(id_image)
from ps_image
where id_product = ps_product_lang.id_product
) as id_img
FROM ps_product_lang
...
I was too much focused on the id_image. What I want is to view an individual product only 1 time. So a simple group by does the job.
SELECT ps_product_lang.id_product , ps_product_lang.name as product_name , ps_product_lang.description_short , ps_product_lang.link_rewrite as product_link_rewrite , ps_product_lang.meta_title , ps_product.reference , ps_product.id_category_default , ps_product.on_sale , ps_product.price , ps_category_lang.name as category_name , ps_category_lang.link_rewrite as category_link_rewrite , ps_image.id_image
FROM ps_product_lang
INNER JOIN ps_product
INNER JOIN ps_category_lang
ON ps_product.id_category_default=ps_category_lang.id_category
INNER JOIN ps_image
ON ps_product_lang.id_product=ps_image.id_product
WHERE ps_product_lang.name LIKE '%simon%' OR ps_product.reference LIKE '%simon%' GROUP BY ps_product_lang.id_product ORDER BY ps_product_lang.id_product ASC

mysql LEFT join for right table max value

I want to select every photo with only one comment and I want that comment to be the one with the maximum ID
I have tried following:
SELECT
p.id,
p.title,
MAX(c.id),
c.comment
FROM tb_photos AS p
LEFT JOIN tb_comments AS c ON p.id=c.photos_id.
It seems to be working, but I am wondering if there is a better way to do this?
you need to apply the max( comment ID ) on each photo (assuming the comment ID is auto-increment and thus always the most recent added to the table)
select
p.*,
tbc.Comment
from
tb_photos p
LEFT JOIN ( select c.photos_id,
max( c.id ) lastCommentPerPhoto
from
tb_comments c
group by
c.photos_id
order by
c.Photos_id ) LastPhotoComment
on p.id = LastPhotoComment.photos_id
LEFT JOIN tb_comments tbc
on LastPhotoComment.LastCommentPerPhoto = tbc.id
You can also do this with a cross join:
select
p.*,
LastPhotoComment.Comment
from
tb_photos p
cross join ( select top 1 c.Comment
from
tb_comments c
where
c.photos_id = p.id
order by
c.id DESC ) LastPhotoComment

MySQL LEFT JOIN, GROUP BY and ORDER BY not working as required

I have a table
'products' => ('product_id', 'name', 'description')
and a table
'product_price' => ('product_price_id', 'product_id', 'price', 'date_updated')
I want to perform a query something like
SELECT `p`.*, `pp`.`price`
FROM `products` `p`
LEFT JOIN `product_price` `pp` ON `pp`.`product_id` = `p`.`product_id`
GROUP BY `p`.`product_id`
ORDER BY `pp`.`date_updated` DESC
As you can probably guess the price changes often and I need to pull out the latest one. The trouble is I cannot work out how to order the LEFT JOINed table. I tried using some of the GROUP BY functions like MAX() but that would only pull out the column not the row.
Thanks.
It appears that it is impossible to use an ORDER BY on a GROUP BY summarisation. My fundamental logic is flawed. I will need to run the following subquery.
SELECT `p`.*, `pp`.`price` FROM `products` `p`
LEFT JOIN (
SELECT `price` FROM `product_price` ORDER BY `date_updated` DESC
) `pp`
ON `p`.`product_id` = `pp`.`product_id`
GROUP BY `p`.`product_id`;
This will take a performance hit but as it is the same subquery for each row it shouldn't be too bad.
You need to set aliases properly I think and also set what you are joining on:
SELECT p.*, pp.price
FROM products AS p
LEFT JOIN product_price AS pp
ON pp.product_id = p.product_id
GROUP BY p.product_id
ORDER BY pp.date_updated DESC
This will give you the last updated price:
select
p.*, pp.price
from
products p,
-- left join this if products may not have an entry in prodcuts_price
-- and you would like to see a null price with the product
join
(
select
product_price_id,
max(date_updated)
from products_price
group by product_price_id
) as pp_max
on p.product_id = pp.product_id
join products_price pp on
pp_max.prodcuts_price_id = pp.products_price_id
Mysqlism:
SELECT p.*, MAX(pp.date_updated), pp.price
FROM products p
LEFT JOIN product_price pp ON pp.product_id = p.product_id
GROUP BY p.product_id
Will work on some RDBMS:
SELECT p.*, pp.date_updated, pp.price
FROM products p
LEFT JOIN product_price pp ON pp.product_id = p.product_id
WHERE (p.product_id, pp.date_updated)
in (select product_id, max(date_updated)
from product_price
group by product_id)
Will work on most RDBMS:
SELECT p.*, pp.date_updated, pp.price
FROM products p
LEFT JOIN product_price pp ON pp.product_id = p.product_id
WHERE EXISTS
(
select null -- inspired by Linq-to-SQL style :-)
from product_price
WHERE product_id = p.product_id
group by product_id
HAVING max(date_updated) = pp.date_updated
)
Will work on all RDBMS:
SELECT p.*, pp.date_updated, pp.price
FROM products p
LEFT JOIN product_price pp ON pp.product_id = p.product_id
LEFT JOIN
(
select product_id, max(date_updated) as recent
from product_price
group by product_id
) AS latest
ON latest.product_id = p.product_id AND latest.recent = pp.date_updated
And if nate c's code intent is to just get one row from product_price, no need to table-derive (i.e. join (select product_price_id, max(date_updated) from products_price) as pp_max), he might as well just simplify(i.e. no need to use the product_price_id surrogate primary key) it like the following:
SELECT p.*, pp.date_updated, pp.price
FROM products p
LEFT JOIN product_price pp ON pp.product_id = p.product_id
WHERE pp.date_updated = (select max(date_updated) from product_price)