I have got two tables. One is for news and second one for images. Each news can have 0-3 images (image_1, image_2, image_3 in table news - its id). Now iam trying to get all rows from images table but its giving me back only one.
Like that (but it is not working)
select news.id as nid, image_1, image_2, image_3, photos.id as pid, big, small
from news
left join photos
on image_1=photos.id, image_2=photos.id, image_3=photos.id
order by nid desc
Even #juergen has suggested better option and also guided you how to solve your problem in your way but if stil you are facing issue how to do then you can follow below query-
SELECT p.id AS pid, n1.image_1, n2.image_2, n3.image_3, big, small
FROM photos AS p
LEFT JOIN news AS n1 ON n1.image_1=p.id
LEFT JOIN news AS n2 ON n2.image_2=p.id
LEFT JOIN news AS n3 ON n1.image_3=p.id
ORDER BY n.id DESC;
You have to join the photos table 3 times with different aliases.
But you actually should rather change your table design. Add another table called news_photos
news_photos table
-----------------
news_id
photo_id
Then you can remove the image columns from the news table.
After the changes you can select news with all photos of like that
select n.*, p.name
from news
left join news_photos np on n.id = np.news_id
left join photos p on p.id = np.photo_id
where n.id = 1234
Related
I have this query that selects a CAR together with it IMAGES from a MySQL database.
SELECT car.*, comments.*, person.*, body_type.* FROM car
INNER JOIN person
ON person.car_id = car.car_id
INNER JOIN comments
ON comments.car_id = car.car_id
INNER JOIN body_type
ON body_type.bodytype_id = car.bodytype_id
INNER JOIN images
ON images.car_id = car.car_id
ORDER BY added_on DESC
However, this actually counts the images from the IMAGES and returns one listing as many times as there are images from the table. For instance, if there are five images from the IMAGES table, it will return one CAR Listing Five times, when I actually want display the five images and associate them with one CAR using the CAR ID. I noticed that the problem was in the query because when I removed INNER JOIN images ON images.car_id = car.car_id, the Cars are displayed just the right way except, without the images.
Do you wand to get the number of images for each car? Maybe this will help you (untested):
SELECT car.*, comments.*, person.*, body_type.*, count(*) as countImages
FROM car
INNER JOIN person
ON person.car_id = car.car_id
INNER JOIN comments
ON comments.car_id = car.car_id
INNER JOIN body_type
ON body_type.bodytype_id = car.bodytype_id
INNER JOIN images
ON images.car_id = car.car_id
GROUP BY car.car_id
ORDER BY added_on DESC
Here's what the table look like:
I'm trying to do a subquery that will pull each image name out for each product. The subquery I got is only pulling the first one out. It may be that I've been looking at it too long or whatever, either way, can someone tell me what I'm doing wrong?
Select c.field_id_33 AS email, o.order_id,c.field_id_76 AS pics, Group_concat(DISTINCT o.entry_id) AS Products,group_concat(DISTINCT t.title),(SELECT field_id_76 FROM finn_channel_data WHERE entry_id = o.entry_id), group_concat(DISTINCT t.url_title) from finn_cartthrob_order_items o
LEFT JOIN finn_channel_data c
ON c.entry_id=o.order_id
LEFT JOIN finn_channel_titles t
ON o.entry_id=t.entry_id
GROUP BY email
I have 3 tables : videos, categories, video_categories.
In videos, I have id, title, and other fields.
In categories, I have id and name.
In video_categories, I have id, video_id, and category_id.
One video can have multiple categories. So the video_categories table will be something like this.
id video_id category_id
1 1 1
2 1 2
3 1 3
If I want to have a list of videos and display their categories, which would be preferred?
Via PHP, call 1 query to get all videos, then loop on that to query to get each video's categories, and another query to get the category name. This will be really slow if the table is huge, right?
Via MySQL joins (need help on this). If I left join videos to video_categories, there will be 3 results of the same video_id. I can use GROUP BY or SELECT DISTINCT to get unique result, but how can I now get the categories' names?
My expected result will be something like this:
id title categories
1 Video1 pop, rock, jazz
For option 2, use GROUP_CONCAT. It will be ok
SELECT v.id, v.title, GROUP_CONCAT(c.name)
FROM videos v
INNER JOIN video_categories vc ON vc.video_id = v.id
INNER JOIN categories c ON vc.category_id = c.id
GROUP BY v.id, v.title
For Group_Concat() function , is the default separator. That's why I don't use it here.
Guessing the names of your other columns..
SELECT v.video_id, v.title, GROUP_CONCAT(c.category_name SEPARATOR ', ')
FROM videos v
LEFT JOIN video_categories vc ON vc.video_id = v.video_id
LEFT JOIN categories c ON c.category_id = vc.category_id
GROUP BY v.video_id, v.title
On a webpage, I am displaying a number of picture collections (I show the thumbnails for each collection). Each picture has five relevant tables:
likes (id, user_id, picture_id),
views (id, user_id, picture_id),
comments (id, user_id, picture_id, comment),
pictures (id (which equals the "picture_id" in the previous tables), collection_id, picture_url and several other columns),
collections (id (equal to collection_id in previous table), and several other columns.
When loading my page, I need to aggregate the number of likes, views and comments for all pictures in each collection, so as to show those numbers under each collection.
So basically: count the likes for each picture, count them all up, display number. Count the views for each picture, count them all up, display number. Count the comments for each picture, count them all up, display number. And then rinse and repeat for all collections.
I'm pretty new at mysql, and I'm struggling between selects, multiple joins, counts, php vs mysql, etc etc. I'm sure there's many ways I can do this that would be very inefficient, so I'm hoping you can tell me the best/fastest/most efficient way to do this.
Thanks in advance!
You can solve this with selects and left joins.
Since you'll count entries on each table for every pictureId, your pictures table will be the left side of each relation. So:
select
p.id as pictureId,
count(distinct l.id) as count_likes,
count(distinct v.id) as count_views,
count(distinct c.id) as count_comments
from
pictures as p
left join likes as l on p.id = l.pictureId
left join views as v on p.id = v.pictureId
left join comments as c on p.id = c.pictureId
group by
p.id
Basically, you are counting every record in each table for each record in the pictures table; if there are no records in likes, views or comments, the count will be zero, respectively.
Of course, you can expand this idea for collections:
select
c.id as collection_id,
p.id as picture_id,
count(distinct l.id) as count_likes,
count(distinct v.id) as count_views,
count(distinct c.id) as count_comments
from
collections as c
left join pictures as p on c.id = p.collection_id
left join likes as l on p.id = l.picture_Id
left join views as v on p.id = v.picture_Id
left join comments as c on p.id = c.picture_Id
group by
c.id,
p.id
If you want to filter your results for each collection, you only need to add where c.id = aValue before the group by (where aValue is the collection Id you want to retrieve)
Hope this helps you.
If you only need the aggregate data for each collection:
select
c.id as collection_id,
count(distinct l.id) as count_likes,
count(distinct v.id) as count_views,
count(distinct c.id) as count_comments
from
collections as c
left join pictures as p on c.id = p.collection_id
left join likes as l on p.id = l.picture_Id
left join views as v on p.id = v.picture_Id
left join comments as c on p.id = c.picture_Id
group by
c.id
This should do the trick ;-)
You could do this with subselects:
SELECT
collections.*,
( SELECT COUNT(*) FROM pictures, likes
WHERE pictures.id = likes.picture_id
AND pictures.collection_id = collection.id
) AS like_count,
( SELECT COUNT(*) FROM pictures, views
WHERE pictures.id = views.picture_id
AND pictures.collection_id = collection.id
) AS view_count,
( SELECT COUNT(*) FROM pictures, comments
WHERE pictures.id = comments.picture_id
AND pictures.collection_id = collection.id
) AS comment_count
FROM collections
WHERE ...
This looks like it's going over the pictures table thrice, but I suspect that MySQL might be able to optimize that using the join buffer. I should note that I haven't actually tested this query, however. I also have no idea how this compares performance-wise with Barranka's LEFT JOIN solution. (Both would be pretty horrible if implemented naïvely, so it comes down to how smart MySQL's query optimizer is in each case.)
I am building a blog with Codeigniter and MySQL. The question I have is this, I have a table with posts and one with categories. I also have a cross reference table with post_categories. What I am trying to do is get all the categories with their names and the number of posts they have under their name.
Example output would be: Hello World(1) Test(0) etc.
What I am having a hard time finding is a SQL query that will join the three tables and get me the counts, and I am also having a hard time wrapping my head around how to make that query.
Here is my table schema:
blgpost
====
id
*Other schema unimportant
blgpostcategories
=================
postid
categoryid
blgcategories
==========
id
name
*Other schema unimportant
This should give you the output you want....
SELECT c.name, COUNT(p.id) FROM
blgcategories c
INNER JOIN blgpostcategories pc ON c.id = pc.categoryid
INNER JOIN blgpost p ON pc.postid = p.id
GROUP BY c.id
You don't need to join the three tables - the blgpost table doesn't have any information in it that you need.
SELECT COUNT(*), blgcategories.name
FROM blgcategories INNER JOIN blgpostcategories
ON blgcategories.id=blgpostcategories.categoryid
GROUP BY blgcategories.id;
SELECT name, COUNT(pc.id)
FROM blgcategories c
LEFT JOIN
blgpostcategories pc
ON pc.categoryid = c.id
GROUP BY
c.id
Using LEFT JOIN will show 0 for empty categories (those without posts linked to them) rather than omitting them.