ORDER BY MySQL and timestamp - mysql

I would like to order my posts by their timestamp but that doesn't and I don't know why.
When I execute my query without order, it works, but when I add ORDER BY it doesn't work.
This is my query :
SELECT * FROM Posts INNER JOIN Topics ON idTopic = idTopics
INNER JOIN Users ON idUserPosts = idUsers
WHERE idTopic = :idTopic LIMIT :limit_down, :limit_up
ORDER BY Posts.datePosts DESC;
Why that doesn't work?

Try inversing the ORDER BY/LIMIT:
SELECT * FROM Posts
INNER JOIN Topics ON idTopic = idTopics
INNER JOIN Users ON idUserPosts = idUsers
WHERE idTopic = :idTopic
ORDER BY Posts.datePosts DESC
LIMIT :limit_down, :limit_up;
The order by needs to be before the limit, else the limit is way less useful: you'd get the X first rows of the table, but "first" using what criteria? And then you'd order those results.
You can do that, too, if you really want to, but think about what you are doing then:
SELECT * FROM (
SELECT Posts.datePosts orderField, * FROM Posts
INNER JOIN Topics ON idTopic = idTopics
INNER JOIN Users ON idUserPosts = idUsers
WHERE idTopic = :idTopic
LIMIT :limit_down, :limit_up;
)
ORDER BY orderField DESC

Try this:
SELECT * FROM Posts INNER JOIN Topics ON idTopic = idTopics
INNER JOIN Users ON idUserPosts = idUsers
WHERE idTopic = :idTopic
ORDER BY Posts.datePosts DESC
LIMIT :limit_down, :limit_up;
Limit must be the last thing applied to a query, so order by needs to come first.

Seems dateposts is a date field then why not try this
SELECT * FROM Posts INNER JOIN Topics ON idTopic = idTopics
INNER JOIN Users ON idUserPosts = idUsers
WHERE idTopic = :idTopic LIMIT :limit_down, :limit_up
ORDER BY DATE(Posts.datePosts) DESC;

Related

Fetch only one record from first order by and rest from second order by

I have a query
SELECT s.*
, g.*
from tbl_section1 as s
, tbl_game as g
LEFT
JOIN tbl_game_visit_count AS gvc
ON g.game_id = gvc.game_id
where s.category_id = g.game_id
ORDER
BY g.udate DESC
, gvc.visit_count DESC
which works fine.
But I want to fetch the first record ordered by g.udate, and then the rest of the records ordered by gvc.visit_count.
Is this possible using mysql query?
Thanks in advance.
It could be possible by using UNION(not UNION ALL, since we don't want to duplicate rows ) between two queries with ORDER BY and LIMIT clauses inside parentheses
SELECT q.*
FROM
(
SELECT s.*, g.*
FROM tbl_section1 as s
INNER JOIN tbl_game as g ON s.category_id = g.game_id
LEFT JOIN tbl_game_visit_count AS gvc ON g.game_id = gvc.game_id
ORDER BY g.udate DESC
LIMIT 1
) q
UNION
SELECT s.*, g.*
FROM tbl_section1 as s
INNER JOIN tbl_game as g ON s.category_id = g.game_id
LEFT JOIN tbl_game_visit_count AS gvc ON g.game_id = gvc.game_id
ORDER BY gvc.visit_count DESC;
P.S. Because of your original query I kept DESC options for ORDER BY, you can get rid of them if you want regular ascending ordering.

INNER JOIN COUNT on same table

here's what I am currently trying to achieve.
I have a users table which I want to join with itself.
So I query all users with no ParentUserId and also want an additional field called ChildrenCount where I can find a count of all users with the ParentUserId = UserId.
SELECT p.*, COUNT(*) as ChildrenCount FROM users p
LEFT JOIN users q
on q.userid = p.ParentUserId
WHERE p.ParentUserId = 0 AND p.CategoryId = 2 ORDER BY p.userid DESC LIMIT 10 OFFSET 0
I am not getting any error but the query isn't working as I expected. I do not get the count of all related children.
Database is MYSQL.
If I understood you correctly,
you can use a correlated query :
SELECT p.*,
(SELECT count(*) FROM users s
WHERE s.parentUserId = p.userid) as ChildrenCount
FROM users p
WHERE p.ParentUserId = 0 AND p.CategoryId = 2
ORDER BY p.userid DESC LIMIT 10 OFFSET 0
I think you don't need join, because you do not select anything from child table:
SELECT p.*, (SELECT COUNT(*) FROM `users` q WHERE q.userid = p.ParentUserId) as ChildrenCount
FROM `users` p
WHERE p.ParentUserId = 0 AND p.CategoryId = 2
ORDER BY p.userid DESC LIMIT 10 OFFSET 0

mysql query optimization steps or how to optimze query

I don't know much about query optimization but I know the order in which queries get executed
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
This the query I had written
SELECT
`main_table`.forum_id,
my_topics.topic_id,
(
SELECT MAX(my_posts.post_id) FROM my_posts WHERE my_topics.topic_id = my_posts.topic_id
) AS `maxpostid`,
(
SELECT my_posts.admin_user_id FROM my_posts WHERE my_topics.topic_id = my_posts.topic_id ORDER BY my_posts.post_id DESC LIMIT 1
) AS `admin_user_id`,
(
SELECT my_posts.user_id FROM my_posts WHERE my_topics.topic_id = my_posts.topic_id ORDER BY my_posts.post_id DESC LIMIT 1
) AS `user_id`,
(
SELECT COUNT(my_topics.topic_id) FROM my_topics WHERE my_topics.forum_id = main_table.forum_id ORDER BY my_topics.forum_id DESC LIMIT 1
) AS `topicscount`,
(
SELECT COUNT(my_posts.post_id) FROM my_posts WHERE my_topics.topic_id = my_posts.topic_id ORDER BY my_topics.topic_id DESC LIMIT 1
) AS `postcount`,
(
SELECT CONCAT(admin_user.firstname,' ',admin_user.lastname) FROM admin_user INNER JOIN my_posts ON my_posts.admin_user_id = admin_user.user_id WHERE my_posts.post_id = maxpostid ORDER BY my_posts.post_id DESC LIMIT 1
) AS `adminname`,
(
SELECT forum_user.nick_name FROM forum_user INNER JOIN my_posts ON my_posts.user_id = forum_user.user_id WHERE my_posts.post_id = maxpostid ORDER BY my_posts.post_id DESC LIMIT 1
) AS `nickname`,
(
SELECT CONCAT(ce1.value,' ',ce2.value) AS fullname FROM my_posts INNER JOIN customer_entity_varchar AS ce1 ON ce1.entity_id = my_posts.user_id INNER JOIN customer_entity_varchar AS ce2 ON ce2.entity_id=my_posts.user_id WHERE (ce1.attribute_id = 1) AND (ce2.attribute_id = 2) AND my_posts.post_id = maxpostid ORDER BY my_posts.post_id DESC LIMIT 1
) AS `fullname`
FROM `my_forums` AS `main_table`
LEFT JOIN `my_topics` ON main_table.forum_id = my_topics.forum_id
WHERE (forum_status = '1')
And now I want to know if there is any way to optimize it ? Because all the logic is written in Select section not From, but I don't know how to write the same logic in From section of the query ?
Does it make any difference or both are same ?
Thanks
Correlated subqueries should really be a last resort, they often end up being executed RBAR, and given that a number of your subqueries are very similar, trying to get the same result using joins is going to result in a lot less table scans.
The first thing I note is that all of your subqueries include the table my_posts, and most contain ORDER BY my_posts.post_id DESC LIMIT 1, those that don't have a count with no group by so the order and limit are redundant anyway, so my first step would be to join to my_posts:
SELECT *
FROM my_forums AS f
LEFT JOIN my_topics AS t
ON f.forum_id = t.forum_id
LEFT JOIN
( SELECT topic_id, MAX(post_id) AS post_id
FROM my_posts
GROUP BY topic_id
) AS Maxp
ON Maxp.topic_id = t.topic_id
LEFT JOIN my_posts AS p
ON p.post_id = Maxp.post_id
WHERE forum_status = '1';
Here the subquery just ensures you get the latest post per topic_id. I have shortened your table aliases here for my convenience, I am not sure why you would use a table alias that is longer than the actual table name?
Now you have the bulk of your query you can start adding in your columns, in order to get the post count, I have added a count to the subquery Maxp, I have also had to add a few more joins to get some of the detail out, such as names:
SELECT f.forum_id,
t.topic_id,
p.post_id AS `maxpostid`,
p.admin_user_id,
p.user_id,
t2.topicscount,
maxp.postcount,
CONCAT(au.firstname,' ',au.lastname) AS adminname,
fu.nick_name AS nickname
CONCAT(ce1.value,' ',ce2.value) AS fullname
FROM my_forums AS f
LEFT JOIN my_topics AS t
ON f.forum_id = t.forum_id
LEFT JOIN
( SELECT topic_id,
MAX(post_id) AS post_id,
COUNT(*) AS postcount
FROM my_posts
GROUP BY topic_id
) AS Maxp
ON Maxp.topic_id = t.topic_id
LEFT JOIN my_posts AS p
ON p.post_id = Maxp.post_id
LEFT JOIN admin_user AS au
ON au.admin_user_id = p.admin_user_id
LEFT JOIN forum_user AS fu
ON fu.user_id = p.user_id
LEFT JOIN customer_entity_varchar AS ce1
ON ce1.entity_id = p.user_id
AND ce1.attribute_id = 1
LEFT JOIN customer_entity_varchar AS ce2
ON ce2.entity_id = p.user_id
AND ce2.attribute_id = 2
LEFT JOIN
( SELECT forum_id, COUNT(*) AS topicscount
FROM my_topics
GROUP BY forum_id
) AS t2
ON t2.forum_id = f.forum_id
WHERE forum_status = '1';
I am not familiar with your schema so the above may need some tweaking, but the principal remains - use JOINs over sub-selects.
The next stage of optimisation I would do is to get rid of your customer_entity_varchar table, or at least stop using it to store things as basic as first name and last name. The Entity-Attribute-Value model is an SQL antipattern, if you added two columns, FirstName and LastName to your forum_user table you would immediately lose two joins from your query. I won't get too involved in the EAV vs Relational debate as this has been extensively discussed a number of times, and I have nothing more to add.
The final stage would be to add appropriate indexes, you are in the best decision to decide what is appropriate, I'd suggest you probably want indexes on at least the foreign keys in each table, possibly more.
EDIT
To get one row per forum_id you would need to use the following:
SELECT f.forum_id,
t.topic_id,
p.post_id AS `maxpostid`,
p.admin_user_id,
p.user_id,
MaxT.topicscount,
maxp.postcount,
CONCAT(au.firstname,' ',au.lastname) AS adminname,
fu.nick_name AS nickname
CONCAT(ce1.value,' ',ce2.value) AS fullname
FROM my_forums AS f
LEFT JOIN
( SELECT t.forum_id,
COUNT(DISTINCT t.topic_id) AS topicscount,
COUNT(*) AS postCount,
MAX(t.topic_ID) AS topic_id
FROM my_topics AS t
INNER JOIN my_posts AS p
ON p.topic_id = p.topic_id
GROUP BY t.forum_id
) AS MaxT
ON MaxT.forum_id = f.forum_id
LEFT JOIN my_topics AS t
ON t.topic_ID = Maxt.topic_ID
LEFT JOIN
( SELECT topic_id, MAX(post_id) AS post_id
FROM my_posts
GROUP BY topic_id
) AS Maxp
ON Maxp.topic_id = t.topic_id
LEFT JOIN my_posts AS p
ON p.post_id = Maxp.post_id
LEFT JOIN admin_user AS au
ON au.admin_user_id = p.admin_user_id
LEFT JOIN forum_user AS fu
ON fu.user_id = p.user_id
LEFT JOIN customer_entity_varchar AS ce1
ON ce1.entity_id = p.user_id
AND ce1.attribute_id = 1
LEFT JOIN customer_entity_varchar AS ce2
ON ce2.entity_id = p.user_id
AND ce2.attribute_id = 2
WHERE forum_status = '1';

Join two tables with condition on the first table

I want to make these two into one SELECT statement:
SELECT *
FROM activegroupmodel
WHERE groupID = ?
ORDER BY groupModelID DESC
LIMIT 1
SELECT *
FROM model
WHERE modelID = ?
As you can see from the first groupID is not a pk and I want the latest model from that table.
I'v tried this but it obviously didn't work:
SELECT *
FROM activegroupmodel as a
WHERE a.groupID = ?
ORDER BY a.groupModelID DESC
LIMIT 1
INNER JOIN model as m ON a.modelID = m.modelID
I've read a bunch of questions with JOIN but none of them matches my problem.
Anybody knows how I can solve this?
Best regards Johan
just put your JOIN before the WHERE condition, like this:
SELECT *
FROM activegroupmodel as a
INNER JOIN model as m ON a.modelID = m.modelID
WHERE a.groupID = ?
ORDER BY a.groupModelID DESC
LIMIT 1
SELECT *
FROM activegroupmodel as a
INNER JOIN model as m ON a.modelID = m.modelID
WHERE a.groupID = ?
ORDER BY a.groupModelID DESC
LIMIT 1
The correct join statement should be as
SELECT *
FROM activegroupmodel as a
INNER JOIN model as m ON a.modelID = m.modelID
WHERE a.groupID = ?
ORDER BY a.groupModelID DESC
LIMIT 1
Try this
SELECT *
FROM activegroupmodel as a
INNER JOIN model as m ON a.modelID = m.modelID
WHERE a.groupID = ?
ORDER BY a.groupModelID DESC
LIMIT 1

mysql multiple fields from subquery

SELECT
(SELECT date FROM forums WHERE topic_id=f.id OR id=f.id ORDER BY id DESC LIMIT 1) as last_reply,
f.*, p.id as pid, p.name FROM forums f
INNER JOIN players p ON p.id = f.author
WHERE f.topic_id=0 ORDER BY f.id DESC
In the subquery, I'd like to return not only the date field, but also the author field as well. how can I do this?
looked at a similar post but can't apply it to mine.
I would do it something like this:
SELECT
(SELECT date FROM forums WHERE topic_id=f.id OR id=f.id ORDER BY id DESC LIMIT 1) as last_reply,
(SELECT author FROM forums WHERE topic_id=f.id OR id=f.id ORDER BY id DESC LIMIT 1) as last_author,
f.*, p.id as pid, p.name FROM forums f
INNER JOIN players p ON p.id = f.author
WHERE f.topic_id=0 ORDER BY f.id DESC
I would actually repeat the subquery again
Maybe something like this can help you :
SELECT MAX(f.date), f.author
FROM forums f
INNER JOIN players p ON
p.id = f.author
WHERE f.tpoic_id = 0
GROUP BY f.author
ORDER BY f.id DESC
But it's difficult with no structure of tables.
Good luck.