I can't see what is wrong with this query. I get an error saying:
"column article_id in from clause is ambiguous"
I understand that it may have something to do with table name aliases but not sure of how to fix. If the query was smaller I may be able to work something out but it's pretty confusing to me and every time I change something to try and fix it, something else stops - so I thought I'd ask first.
SELECT bt.topic_title, f.article_id, p.photo_id, ba.title, ba.slug,
IFNULL(c.cnt,0) comments, IFNULL(ph.cnt,0) photos, IFNULL(v.cnt,0) videos
FROM blog_article_followers AS f
LEFT OUTER JOIN (
SELECT article_id, COUNT(comment_id) as cnt
FROM blog_comments
GROUP BY article_id) c
ON f.article_id = c.article_id
LEFT OUTER JOIN (" _
SELECT article_id, COUNT(photo_id) as cnt
FROM photos
GROUP BY article_id) ph
ON f.article_id = ph.article_id
LEFT OUTER JOIN (
SELECT article_id, COUNT(video_id) as cnt
FROM videos
GROUP BY article_id) v
ON f.article_id = v.article_id
LEFT JOIN blog_topics bt ON f.topic_id = bt.topic_id
LEFT JOIN blog_articles AS ba USING (article_id)
LEFT JOIN photos AS p USING (article_id)
WHERE f.member_id = 100 AND p.cover = 1
ORDER BY f.follow_date DESC;
Try replacing this:
LEFT JOIN blog_articles AS ba USING (article_id)
LEFT JOIN photos AS p USING (article_id)
With this
LEFT JOIN blog_articles AS ba ON f.article_id = ba.article_id
LEFT JOIN photos AS p ON f.article_id = photos.article_id
you have to rename the column
LEFT JOIN photos AS p USING (p.article_id)
or to whichever table article_id belongs to
Related
We are maintaining a history of Content. We want to get the updated entry of each content, with create Time and update Time should be of the first entry of the Content. The query contains multiple selects and where clauses with so many left joins. The dataset is very huge, thereby query is taking more than 60 seconds to execute. Kindly help in improving the same. Query:
select * from (select * from (
SELECT c.*, initCMS.initcreatetime, initCMS.initupdatetime, user.name as partnerName, r.name as rightsName, r1.name as copyRightsName, a.name as agelimitName, ct.type as contenttypename, cat.name as categoryname, lang.name as languagename FROM ContentCMS c
left join ContentCategoryType ct on ct.id = c.contentType
left join User user on c.contentPartnerId = user.id
left join Category cat on cat.id = c.categoryId
left join Language lang on lang.id = c.languageCode
left join CopyRights r on c.rights = r.id
left join CopyRights r1 on c.copyrights = r1.id
left join Age a on c.ageLimit = a.id
left outer join (
SELECT contentId, createTime as initcreatetime, updateTime as initupdatetime from ContentCMS cms where cms.deleted='0'
) as initCMS on initCMS.contentId = c.contentId WHERE c.deleted='0' order by c.id DESC
) as temp group by contentId) as c where c.editedBy='0'
Any help would be highly appreciated. Thank you.
Just a partial eval and suggestion because your query seems non properly formed
This left join seems unuseful
FROM ContentCMS c
......
left join (
SELECT contentId
, createTime as initcreatetime
, updateTime as initupdatetime
from ContentCMS cms
where cms.deleted='0'
) as initCMS on initCMS.contentId = c.contentId
same table
the order by (without limit) in a subquery in join is unuseful because join ordered values or unordered value produce the same result
the group by contentId is strange beacuse there aren't aggregation function and the sue of group by without aggregation function is deprecated is sql
and in the most recente version for mysql is not allowed (by deafult) if you need distinct value or just a rows for each contentId you should use distinct or retrive the value in a not casual manner (the use of group by without aggregation function retrive casual value for not aggregated column .
for a partial eval your query should be refactored as
SELECT c.*
, c.initcreatetime
, c.initupdatetime
, user.name as partnerName
, r.name as rightsName
, r1.name as copyRightsName
, a.name as agelimitName
, ct.type as contenttypename
, cat.name as categoryname
, lang.name as languagename
FROM ContentCMS c
left join ContentCategoryType ct on ct.id = c.contentType
left join User user on c.contentPartnerId = user.id
left join Category cat on cat.id = c.categoryId
left join Language lang on lang.id = c.languageCode
left join CopyRights r on c.rights = r.id
left join CopyRights r1 on c.copyrights = r1.id
WHERE c.deleted='0'
) as temp
for the rest you should expiclitally select the column you effectively need add proper aggregation function for the others
Also the nested subquery just for improperly reduce the rows don't help performance ... you should also re-eval you data modelling and design.
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.
I got this simple join statement and I'm pretty sure the syntax is correct. I looked some tutorials and I don't find any difference between my code and the exemples.
Here's the statement:
SELECT n.id nId, n.news_date, n.news_type,
p.id pId, p.title pTitle, p.file_path pPath,
s.id sId, s.title sTitle, s.content sContent,
v.id vId, v.title vTitle, v.url vUrl
FROM photo_news p, standard_news s, video_news v
INNER JOIN news n
ON p.news_id = n.id OR s.news_id = n.id OR v.news_id = n.id
ORDER BY n.news_date DESC
I get the following error:
Unknown column 's.news_id' in 'on clause'
I really don't know why this error is launched because the column 'news_id' exists in every table it has to exist.
And if I change the order in the ON clause (i.e. I start with p.news_id = n.news_id) I get the same error (unknwonw column p.news_id). So I think there's a problem with the aliases but I really don't have a clue.
Thanks for your help ;)
Probably you are looking for something like this to return data for the record in photo news with data in at least one of the other table.
In that case you need to use a LEFT JOINs and not OR in the JOIN conditions.
SELECT n.id nId, n.news_date, n.news_type,
p.id pId, p.title pTitle, p.file_path pPath,
s.id sId, s.title sTitle, s.content sContent,
v.id vId, v.title vTitle, v.url vUrl
FROM news n
LEFT OUTER JOIN photo_news p
ON n.id = p.news_id
LEFT OUTER JOIN standard_news s
ON n.id = s.news_id
LEFT OUTER JOIN video_news v
ON n.id = v.news_id
WHERE p.news_id IS NOT NULL
OR s.news_id IS NOT NULL
OR v.news_id IS NOT NULL
ORDER BY n.news_date DESC
Try this, You made mistake in JOINing tables.
for reference you can see how multiple tables are JOINed together.
SELECT n.id nId, n.news_date, n.news_type,
p.id pId, p.title pTitle, p.file_path pPath,
s.id sId, s.title sTitle, s.content sContent,
v.id vId, v.title vTitle, v.url vUrl
FROM photo_news p INNER JOIN standard_news s
p.news_id = s.news_id
INNER JOIN video_news v
on s.news_id = v.news_id
INNER JOIN news n
on v.news_id = n.id
ORDER BY n.news_date DESC
You are mixing only-style and new-style joins. Just use the explicit join syntax. Your from should probably be:
FROM news n join
photo_news p
on p.news_id = n.id join
standard_news s
on s.news_id = n.id join
video_news v
on v.news_id = n.id
Using or between join conditions is not typically used.
THe error is appearing because of the precedence rules that MySQL uses. As the documentation explains:
INNER JOIN and , (comma) are semantically equivalent in the absence of
a join condition: both produce a Cartesian product between the
specified tables (that is, each and every row in the first table is
joined to each and every row in the second table).
However, the precedence of the comma operator is less than of INNER
JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with
the other join types when there is a join condition, an error of the
form Unknown column 'col_name' in 'on clause' may occur. Information
about dealing with this problem is given later in this section.
All that said, I'm not sure that this is really the query that you want. You are going to get a cartesian product of the different values from the different tables. You should probably ask another question with sample data and desired results, so someone can help you with the right query.
You are using deprecated join syntax mixed with supported syntax.
do yourself a favor and write those joins properly
http://dev.mysql.com/doc/refman/5.0/en/join.html
SELECT n.id nId, n.news_date, n.news_type,
p.id pId, p.title pTitle, p.file_path pPath,
s.id sId, s.title sTitle, s.content sContent,
v.id vId, v.title vTitle, v.url vUrl
FROM photo_news p
left/inner/right/"" join standard_news s on CONDITION
left/inner/right/"" join video_news v on CONDITION
INNER JOIN news n
ON p.news_id = n.id OR s.news_id = n.id OR v.news_id = n.id
ORDER BY n.news_date DESC
However, i am pretty sure you want to use union or something
SELECT ...
FROM
select * from (photo_news p
union all standard_news s
union all video_news v ) all_news
INNER JOIN news n on CONDITION
I use this query to select all articles :
SELECT articles.*,categories.category_name,users.username,tags.tag
FROM articles
LEFT JOIN `categories` ON articles.category_id = categories.category_id
LEFT JOIN `users` ON articles.author_id = users.user_id
LEFT JOIN `tags` ON articles.article_id = tags.article_id
ORDER BY articles.date_added DESC
I have an other table comments, and I want to count how many comments are there, where the article_id in that table = article_id in the articles table. I tried with COUNT, but then it returns only one result. How can I do that with one query?
You can use a subquery in the SELECT clause:
SELECT articles.*,categories.category_name,users.username,tags.tag, (SELECT count(*) FROM comments c WHERE c.article_id = articles.article_id) as comments_count
As arnaud576875 already stated, you can use a subquery to extract the summary data.
Two things I've noticed from your SQL that are not really a part of the question but still worth pointing out.
you can use a table alias to shorten your SQL and make it more readable.
So instead of
SELECT articles.*,categories.category_name,users.username,tags.tag
FROM articles
LEFT JOIN `categories` ON articles.category_id = categories.category_id
LEFT JOIN `users` ON articles.author_id = users.user_id
LEFT JOIN `tags` ON articles.article_id = tags.article_id
ORDER BY articles.date_added DESC
you'd code
SELECT a.*, c.category_name, u.username, t.tag
FROM articles a
LEFT JOIN `categories` c ON a.category_id = c.category_id
LEFT JOIN `users` u ON a.author_id = u.user_id
LEFT JOIN `tags` t ON a.article_id = t.article_id
ORDER BY a.date_added DESC
I would drop SELECT * and select only the fields that you actually are going to use. This also helps with readability of your code.
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