Limit values for the left Join part of a query - php

Please i have four tables joined together using the LEFT JOIN, the images table is linked to the items table by img_item, thus each item can have more images. i want to fetch only the first image of every item. How do i go achieve this.
SELECT * FROM items
LEFT JOIN category ON items.item_cat = category.cat_id
LEFT JOIN users ON users.user_id=items.item_user
LEFT JOIN institutions ON institutions.inst_id=users.user_inst
LEFT JOIN images ON images.img_item = items.item_id
ORDER BY item_id DESC

In MySQL, you can enumerate the results using variables, and then choose the first. Another alternative is to identify which one you want, and choose that one. The following chooses the image with the largest id:
SELECT *
FROM items LEFT JOIN
category
ON items.item_cat = category.cat_id LEFT JOIN
users
ON users.user_id=items.item_user LEFT JOIN
institutions
ON institutions.inst_id = users.user_inst LEFT JOIN
images
ON images.img_item = items.item_id AND
images.img_id = (SELECT MAX(i2.img_id)
FROM images i2
WHERE i2.img_item = images.img_item
);
ORDER BY item_id DESC

Related

select from 2 different mysql tables

I have 2 tables one for products and one for images i need to get all products with its related images. and all products with only one image for each
get all products with its related images
Do a inner join like
select p.product_title,
i.*
from products p join images i on p.product_id = i.image_product;
all products with only one image for each
Perform a group by and then join like
select p.*
from products p join (
select img_product
from images
group by img_product
having count(distinct img_product) = 1) xxx on p.product_id = xxx.img_product;

How to select the data from a table when it's ability is in an other table?

I have 3 tables:
-Sales
-Items_cstm
-Items
Sales and Items_cstm contains the data I have to get with the query and Items the ability of the item "Deleted (1 or 0)" (and dome more info I don't need).
The Items_cstm's id is = Items's id.
I have to list the Sales of the Items which aren't deleted (0).
I've tried somehow with inner join but it didn't work and I don't really know what am I doing wrong:
SELECT Items_cstm.quantity
FROM Items_cstm, Sales
WHERE '".$_POST['name']."' = Sales.name
AND
INNER JOIN Items ON Items_cstm.id = Items.id
WHERE Items.deleted = 0;
You can join your tables like this (but you did not show the link between Items_cstm and sales - you have to modify that)
SELECT ic.quantity
FROM Items_cstm ic
INNER JOIN Sales s on s.id = ic.id
INNER JOIN Items i ON ic.id = i.id
WHERE i.deleted = 0
AND s.name = '".$escapedName."'
Also always escape your user input.
Try something like this:
SELECT Items_cstm.quantity
FROM Items_cstm
INNER JOIN Sales ON sales.JOINCOLUMN = Items_cstm.JOINCOLUMN
INNER JOIN Items ON Items_cstm.id = Items.id
WHERE Sales.name = '".$_POST['name']."'
WHERE Items.deleted = 0;
Replace JOINCOLUMN above with the columns that let you match records between these two tables
Something like this should work:
SELECT Items_cstm.quantity
FROM Items_cstm
INNER JOIN Items ON Items_cstm.id = Items.id
INNER JOIN Sales ON Items_cstm.id = Sales.item_id // ??? check this one for column names
WHERE '$name' = Sales.name AND Items.deleted = 0;
Beware of SQL injection.

mysql query dont gets all posts

I have a MYSQL query who have to list all post i want it to post. But it dont do it. It shows posts when i have more then one post in the table "meaOrder" with the same "ordCode". But when i have only on post in meaOrder, i don't show it. What can i do?
SELECT koden, wish, rnamn, bild, pris, cname, onsktext
FROM (
SELECT m.wishText as onsktext, m.meaOID as midn, m.ordcode as koden, w.wish as wish, r.meaName as rnamn, r.meaImg as bild,
r.meaPrice as pris, k.catName as cname from cats k, meals r, wishes w,
meaOrder m
join orders c on c.ordNR=4401
WHERE c.ordStatus=1 AND m.ordNR=c.ordNR AND m.meaID=r.meaID AND m.wishesID=w.id
AND r.catID=k.catID
) T
GROUP BY koden, rnamn, bild, pris, cname
ORDER BY midn DESC
TABLE orders
http://grab.by/m74E
TABLE meaOrder http://grab.by/m74Q
Try replacing the JOIN with RIGHT JOIN in this case. The difference is explained at JOIN Syntax page in MySQL docs . In short - JOIN returns row only if there are corresponding rows in both joined tables (inner join). LEFT JOIN / RIGHT JOIN return all rows from one of the tables and corresponding row if it exists from the other table (those are outer joins)
Do you need a subselect?
This seems to cover it:-
SELECT m.ordcode AS koden, w.wish AS wish, r.meaName AS rnamn, r.meaImg AS bild, r.meaPrice AS pris, k.catName AS cname, m.wishText AS onsktext
FROM cats k
INNER JOIN meals r ON r.catID = k.catID
INNER JOIN meaOrder m ON m.meaID = r.meaID
INNER JOIN wishes w ON m.wishesID = w.id
INNER JOIN orders c ON m.ordNR = c.ordNR
WHERE c.ordStatus = 1
AND c.ordNR = 4401
GROUP BY m.ordcode, r.meaName, r.meaImg, r.meaPrice, k.catName
ORDER BY midn DESC

Selecting multiple counts with left outer join

I've got 3 tables: Product, Shares, Likes which are connected by ProductID. What I want to do is to select all products and COUNT(shares) and COUNT(likes) of these products in one query.
First of all is it possible to do with just one query? If possible how can i do it? And most importantly should I select all products and display then when users hover on make an Ajax call and get like and share data? Thanks in advance.
Here you go:
SELECT
p.id AS 'product id',
IFNULL(COUNT(DISTINCT s.id), 0) AS 'total shares',
IFNULL(COUNT(DISTINCT l.id), 0) AS 'total likes'
FROM
products p
LEFT JOIN shares s ON s.product_id = p.id
LEFT JOIN likes l ON l.product_id = p.id
GROUP BY p.id
IFNULL will treat cases when there are no shares or likes; DISTINCT should be there because otherwise one share will be counted multiple times when joined with likes (and vice versa).
Its possible to do it on one query. Off the top of my head something like
SELECT
product_id,
COUNT(likes.product_id) as likes,
COUNT(SELECT share_id FROM shares WHERE product_id = p.product_id) as shares
FROM product p
LEFT JOIN likes USING(product_id)
Do watch performance though. Make sure you have your indexes etc
SELECT
p.ProductID,
COUNT(s.ProductID) AS SharesCount,
COUNT(l.ProductID) AS LikesCount
FROM
Products p LEFT JOIN Shares s
ON P.ProductID = s.ProductID
LEFT JOIN likes l
ON P.ProductID = l.ProductID
GROUP BY p.ProductID

SQL/PHP: SELECT only one row per item

I have a table containing persons information (one row per person) and another table containing persons photos filenames (many rows per person). I want to select a group of persons (based on another table) but only one photo per person.
My old SQL was like this:
SELECT persons.personID, persons.name, persons.photo_filename, movie_cast.role
FROM persons, movie_cast
WHERE persons.personID = movie_cast.personID
AND movie_cast.imdbID = ?
ORDER BY movie_cast.castORDER
LIMIT 9';
But here, the 'persons' table contains also a 'photo_filename' column. In my new database design, this column is in another table. So if I try to get the photo_filename from the new table I get all the photos available for each person, but I need to get only one.
How to do it?
In the first example I have assumed there is always a photo, and am just grabbing the highest sorted photo filename alphabetically as a means to get a consistent photo for each user each time you run the query.
SELECT p.personID, p.name, ph.photo_filename, mc.role
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID
INNER JOIN (
select personID, max(photo_filename) as MaxPhotoName
from photos
group by personID
) phm on p.personID = phm.personID
INNER JOIN photos ph on phm.personID = ph.personID
and phm.MaxPhotoName = ph.photo_filename
WHERE mc.imdbID = ?
ORDER BY mc.cast
LIMIT 9
If there is a photo_date column and you want to use the newest photo you can do it like this:
SELECT p.personID, p.name, ph.photo_filename, mc.role
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID
INNER JOIN (
select personID, max(photo_date) as MaxPhotoDate
from photos
group by personID
) phm on p.personID = phm.personID
INNER JOIN photos ph on phm.personID = ph.personID
and phm.MaxPhotoDate = ph.photo_date
WHERE mc.imdbID = ?
ORDER BY mc.cast
LIMIT 9
If there is not always a photo, you can use a LEFT OUTER JOIN so that you will still get all your records back:
SELECT p.personID, p.name, ph.photo_filename, mc.role
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID
LEFT OUTER JOIN (
select personID, max(photo_date) as MaxPhotoDate
from photos
group by personID
) phm on p.personID = phm.personID
LEFT OUTER JOIN photos ph on phm.personID = ph.personID
and phm.MaxPhotoDate = ph.photo_date
WHERE mc.imdbID = ?
ORDER BY mc.cast
LIMIT 9

Categories