Join with multiple queries in SQL - mysql

I have this query already:
SELECT * FROM (SELECT * FROM `prefix_messages`
WHERE `category_id`=4
ORDER BY `id` DESC LIMIT 30) ilv
ORDER BY `id` ASC
How to use join query to add data from users table if in prefix_messages I have user_id column?
Thanx!

Try this:
SELECT * FROM (SELECT pm.ID as prefixID, * FROM prefix_messages as pm
INNER JOIN users as u
ON pm.User_id = u.UserId
WHERE pm.category_id=4
ORDER BY pm.id DESC LIMIT 30)
ORDER BY prefixID ASC
I assume that you are only doing the subselect because you want to reverse the order after you get the top 30?

Related

Solution to MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

For some reason MYSQL doesn't support LIMIT inside a subquery:
SELECT m.*
FROM `my_table` m
WHERE m.`id` IN (
SELECT o.`id`
FROM (SELECT DISTINCT i.`id`, i.`label`, i.`client`, i.`place`
FROM `my_table` i
ORDER BY i.`label`, -i.`client` DESC, -i.`place` DESC) o
WHERE m.`label` = o.`label` LIMIT 1
);
I've tried using join from this link: INNER JOIN INSTEAD OF IN(LIMIT error) but not succeeded. Has anyone any clues for it? Thanks.
Since the subquery returns only 1 row with 1 column there is no need for IN.
You can use =:
SELECT m.*
FROM `my_table` m
WHERE m.`id` = (
SELECT o.`id`
FROM (
SELECT DISTINCT i.`id`, i.`label`, i.`client`, i.`place`
FROM `my_table` i
ORDER BY i.`label`, -i.`client` DESC, -i.`place` DESC) o
WHERE m.`label` = o.`label` LIMIT 1
);
But as it is written, your query uses LIMIT without ORDER BY (you do use ORDER BY in the inner subquery where it is useless).
Do you mean to do something like this:
SELECT m.*
FROM `my_table` m
WHERE m.`id` = (
SELECT o.`id`
FROM (
SELECT DISTINCT i.`id`, i.`label`, i.`client`, i.`place`
FROM `my_table` i
) o
WHERE m.`label` = o.`label`
ORDER BY o.`label`, -o.`client` DESC, -o.`place` DESC
LIMIT 1
);
Also ordering by the negative value of a column descending is equivalent to ordering just ascending, so the ORDER BY clause can be simplified to:
ORDER BY o.`label`, o.`client`, o.`place`

MySQL converting subquery to join

Is it possible to convert this subquery to join?
SELECT `news`.`newsId`,
(SELECT `comments`.`text`
FROM `comments`
WHERE `comments`.`newsId` = `news`.`newsId`
order by `comments`.`date` desc
limit 1)
FROM `news` , `comments`
where `news`.`newsId` = `comments`.`newsId`
GROUP BY `news`.`newsId`
order by news.date desc;
I assume newsId is unique.
SELECT `news`.`newsId`,
`comments`.`text`
FROM `news`
CROSS APPLY (SELECT `comments`.`text`
FROM `comments`
WHERE `comments`.`newsId` = `news`.`newsId`
order by `comments`.`date` desc
limit 1) cm
order by news.date desc;
I think that what you're trying to do is:
SELECT n.newsId FROM news n
INNER JOIN comments c ON c.newsId = n.newsId
ORDER BY c.date DESC, n.date
LIMIT 1
The GROUP BY is not necessary as you are not using any aggregation function. You can have unique entries with DISTINCT

MySQL query usage of Order by ASC and DESC

I have this query:
SELECT * FROM project as p inner join users as u on p.user_id = u.user_id
ORDER BY p.projectname, u.date_joined
Now what I want to ORDER by projectname ASC and u.date_joined DESC.
How could I make it this way? I tried this code here but doesn't work:
SELECT * FROM project as p inner join users as u on p.user_id = u.user_id
ORDER BY p.projectname ASC, u.date_joined DESC
Order the projectname ascending works but the descending won't work.
To order project name descending, do this:
SELECT *
FROM project p
INNER JOIN users u ON p.user_id = u.user_id
ORDER BY p.projectname DESC, u.date_joined DESC
This will order your result by projectname desc (Z to A) first. For identical projectname records, date_joined will be used for sorting further (latest date first).

MySQL JOIN + Subquery Query Optimization

I'm trying to fetch 100 posts and order them by the number of times they've been "remixed" in the last week. Here is my query thus far:
SELECT COUNT(remixes.post_id) AS count, posts.title
FROM posts
LEFT JOIN (
SELECT * FROM remixes WHERE created_at >= 1343053513
) AS remixes ON posts.id = remixes.post_id
GROUP BY posts.id
ORDER BY count DESC, posts.created_at DESC
LIMIT 100
This produces the correct result; however, after running DESCRIBE I get this:
And here are my indexes on posts:
And my indexes on remixes:
And here are my questions:
Can you explain what the terms used in the extra column are really trying to tell me?
Could you provide tips on how I can optimize this query so that it'll scale better.
Thanks in advance!
Update
Per Zane's solution, I've updated my query to:
SELECT COUNT(remixes.post_id) AS count, posts.title
FROM posts
LEFT JOIN remixes ON posts.id = remixes.post_id AND remixes.created_at >= 1343053513
GROUP BY posts.id
ORDER BY count DESC, posts.created_at DESC
LIMIT 100
And here's the latest DESCRIBE
I'm still worried about the filesort part. Any ideas?
Try not to wrap your JOIN in a sub-select as this will create an unindexed temporary table to store the result of the subselect in, where it then joins on that unindexed table.
Instead, put created_at as an additional join condition when joining the remixes table:
SELECT
a.title, COUNT(b.post_id) AS remixcnt
FROM
posts a
LEFT JOIN
remixes b ON a.id = b.post_id AND b.created_at >= 1343053513
GROUP BY
a.id, a.title
ORDER BY
remixcnt DESC, a.created_at DESC
LIMIT 100
It seems to me that
SELECT COUNT(remixes.post_id) AS count, posts.title
FROM posts
LEFT JOIN (
SELECT * FROM remixes WHERE created_at >= 1343053513
) AS remixes ON posts.id = remixes.post_id
GROUP BY posts.id
ORDER BY count DESC, posts.created_at DESC
LIMIT 100
could be rewritten as
SELECT COUNT(r.post_id) AS count, posts.title
FROM posts
LEFT JOIN remixes r ON posts.id = r.post_id
WHERE r.created_at >= 1343053513
GROUP BY posts.id
ORDER BY count DESC, posts.created_at DESC
LIMIT 100
which should give you a better EXPLAIN plan and run faster.

problem in mysql query with join and limit the time

i have this
SELECT COUNT(1) cnt, a.auther_id
FROM `posts` a
LEFT JOIN users u ON a.auther_id = u.id
GROUP BY a.auther_id
ORDER BY cnt DESC
LIMIT 20
its work fine
bu now i want select from posts which added from 1 day tried to use
WHERE from_unixtime(post_time) >= SUBDATE(NOW(),1)
but its didnot worked
any one have idea
My guess is that you added the WHERE clause in the wrong place. It should come after the JOIN but before the GROUP BY, like this:
SELECT COUNT(1) cnt, a.auther_id
FROM `posts` a
LEFT JOIN users u ON a.auther_id = u.id
WHERE from_unixtime(post_time) >= SUBDATE(NOW(),1)
GROUP BY a.auther_id
ORDER BY cnt DESC
LIMIT 20