Sorting result in descending order - mysql

I want my results to be sorted by a.right (It might have 2 values: 1 - true, 0 - false). The row where a.right=1 must come first. Tried GROUP BY. But didn't help. How to achieve result above?
SELECT
u.fullname,
a.id,
a.content,
a.addDT,
a.`right`,
acr.score,
acr.checkDT
FROM
answers a
INNER JOIN users u ON u.id = a.uid
LEFT JOIN `answer_chk_results` acr ON acr.aid = a.id
WHERE
a.qid = 1
GROUP BY
a.`right` DESC

A little mistake. Try ORDER BY instead of GROUP BY. ORDER BY is used for sorting records while GROUP BY is used for aggregating records.
Your query should be
SELECT
u.fullname,
a.id,
a.content,
a.addDT,
a.`right`,
acr.score,
acr.checkDT
FROM
answers a
INNER JOIN users u ON u.id = a.uid
LEFT JOIN `answer_chk_results` acr ON acr.aid = a.id
WHERE
a.qid = 1
ORDER BY
a.`right` DESC

You should use ORDER BY for sorting results. GROUP BY is for aggregating the results.

For sorting you should use ORDER BY:
SELECT
u.fullname,
a.id,
a.content,
a.addDT,
a.`right`,
acr.score,
acr.checkDT
FROM
answers a
INNER JOIN users u ON u.id = a.uid
LEFT JOIN `answer_chk_results` acr ON acr.aid = a.id
WHERE
a.qid = 1
ORDER BY
a.`right` DESC

Try appending this to the end:
ORDER BY
a.right DESC

Related

Display results which have no count/zero as well

I am trying to get a count of the number of logins during a given timeframe, currently my SQL query displays only results that had at least one login, I'd like it to display even those which have zero logins.
Query i'm using:
SELECT c.FullName, COUNT(l.Id)
FROM LoginsTable l JOIN UsersTable u ON u.Email = l.Email JOIN Organisations c ON c.Id = u.OrganisationId
WHERE l.AttemptTime > "2019-10-01" AND l.AttemptTime < "2019-11-01" AND l.Success = 1
GROUP BY c.Name
ORDER BY c.Name ASC;
You have a few issues. Firstly, you either need to use a RIGHT JOIN from LoginsTable or reorder the JOINs to put the JOIN to LoginsTable last and use a LEFT JOIN. Given the nature of your query the latter probably makes more sense.
Secondly, you need to put any conditions on fields from a table which has been LEFT JOINed into the join condition, otherwise MySQL converts the LEFT JOIN into an INNER JOIN (see the manual). Finally, you should GROUP BY the same fields as specified in your SELECT. This should work:
SELECT c.FullName, COUNT(l.Id)
FROM Organisations c
JOIN UsersTable u ON u.OrganisationId = c.Id
LEFT JOIN LoginsTable l ON u.Email = l.Email AND l.AttemptTime > "2019-10-01" AND l.AttemptTime < "2019-11-01" AND l.Success = 1
GROUP BY c.FullName
ORDER BY c.FullName
I found 2 issues here:
your group by column is not listed on your column
date condition is using double quotes.
try below query.
SELECT c.FullName, COUNT(l.Id)
FROM LoginsTable l
LEFT JOIN UsersTable u ON u.Email = l.Email
LEFT JOIN Organisations c ON c.Id = u.OrganisationId
WHERE l.AttemptTime between '2019-10-01' AND '2019-11-01' AND l.Success = 1
GROUP BY c.FullName
ORDER BY c.FullName ASC;
As Roman Hocke said you need to use left join as below :
SELECT c.FullName, COUNT(l.Id)
FROM UsersTable u
JOIN Organisations c ON c.Id = u.OrganisationId
LEFT JOIN LoginsTable l ON u.Email = l.Email
WHERE l.AttemptTime > "2019-10-01" AND l.AttemptTime < "2019-11-01" AND l.Success = 1
GROUP BY c.Name
ORDER BY c.Name ASC;
Moreover, you should fix your group by or select using the same field : SELECT c.Name or GROUP BY c.FullName ORDER BY c.FullName
EDIT : Nick's answer is the one. As he said perfectly well, you need to put your conditions in the on clause of your left join.
SELECT c.FullName, COUNT(l.Id)
FROM UsersTable u
JOIN Organisations c ON c.Id = u.OrganisationId
LEFT JOIN LoginsTable l ON (u.Email = l.Email AND l.AttemptTime > "2019-10-01" AND l.AttemptTime < "2019-11-01" AND l.Success = 1)
GROUP BY c.FullName
ORDER BY c.FullName ASC;

INNER JOIN LIMIT 1 WITH USING PAGINATION

How do i limit inner join to 1 with order by DESC on this part
INNER JOIN comments ON thread.t=comments.comment_id
this is my code https://gist.github.com/anonymous/cf7de8400327b98631d2f6d9b23084b5
look at result output there is the problem on duplicate content because of comments (need to limit 1) #M Khalid Junaid
Do a self join to your comments table to pick the recent comment only for each post
SELECT
t.t_dp,
t.t,
t.t_id,
t.tittle,
t.t_username,
t.t_date_posting,
t.views,
c.comments,
c.comment_time,
c.comment_id,
c.c
FROM
thread t
INNER JOIN comments c
ON t.t = c.comment_id
LEFT JOIN comments c1
ON c.comment_id = c1.comment_id
AND c.id < c1.id
WHERE t.t_type = '02'
AND c1.id IS NULL
LIMIT #start_from, #results_per_page
Also you are using LIMIT without ORDER BY which makes no sense, In which order limit applies on records.

How to use ORDER BY in a query which is containing JOIN?

I have a query which selects all comments for each post. Here is my query:
SELECT c.id, c.content, u.name, u.reputation, SUM(v.value) AS total_vote_comments
FROM comments c
INNER JOIN users u ON c.user_id = u.id
LEFT JOIN votes_comments v ON c.id = v.comment_id
WHERE c.post_id = :id;
Now I want to add ORDER BY c.id to that query. How?
An order by is irrelevant because this query returns one row:
SELECT c.id, c.content, u.name, u.reputation, SUM(v.value) AS total_vote_comments
FROM comments c INNER JOIN
users u
ON c.user_id = u.id LEFT JOIN
votes_comments v
ON c.id = v.comment_id
WHERE c.post_id = :id;
This is an aggregation query (because of the SUM()) without a GROUP BY. Such a query always returns one row, even when no rows match the join.
You probably want a GROUP BY. My best guess is:
SELECT c.id, c.content, u.name, u.reputation, SUM(v.value) AS total_vote_comments
FROM comments c INNER JOIN
users u
ON c.user_id = u.id LEFT JOIN
votes_comments v
ON c.id = v.comment_id
WHERE c.post_id = :id
GROUP BY c.id, c.content, u.name, u.reputation
ORDER BY c.id;
You can just add the ORDER BY clause at the end:
SELECT c.id, c.content, u.name, u.reputation, SUM(v.value) AS total_vote_comments
FROM comments c
INNER JOIN users u ON c.user_id = u.id
LEFT JOIN votes_comments v ON c.id = v.comment_id
WHERE c.post_id = :id
ORDER BY c.id;
By using this query you get only one row which id you put in where clause.
If you want to get one post ordered then you write order by in last.
If you want to get last's comment first so use desc with order by.
SELECT c.id, c.content, u.name, u.reputation, SUM(v.value) AS total_vote_commentFROM comments c INNER JOIN users u ON c.user_id = u.id LEFT JOIN votes_comments v ON c.id = v.comment_id WHERE c.post_id = :id order by id desc;
desc = descending order
asc = ascending order

MySQL Unknown column issue

Here is my database structure
https://docs.google.com/open?id=0B9ExyO6ktYcOenZ1WlBwdlY2R3c
My SQL query looks like that
SELECT
u.fullname,
a.id,
a.content,
a.addDT,
a.`right`,
acr.score,
acr.checkDT
FROM
answers a,
users u
LEFT JOIN `answer_chk_results` acr ON acr.aid = a.id
WHERE
a.qid = 7
AND u.id = a.uid
GROUP BY
a.`right` DESC
Getting error message
[Err] 1054 - Unknown column 'a.id' in 'on clause'
I'm pretty sure that a.id column exists
What am I missing?
you can't mix join syntax with comma delimited table syntax. If you are going to left join, you need to use an inner join for the other two tables.
SELECT
u.fullname,
a.id,
a.content,
a.addDT,
a.`right`,
acr.score,
acr.checkDT
FROM
answers a
INNER JOIN users u ON u.id = a.uid
LEFT JOIN `answer_chk_results` acr ON acr.aid = a.id
WHERE
a.qid = 7
GROUP BY
a.`right` DESC
This might work also, but is not guranteed:
SELECT
u.fullname,
a.id,
a.content,
a.addDT,
a.`right`,
acr.score,
acr.checkDT
FROM
(answers a,
users u)
LEFT JOIN `answer_chk_results` acr ON acr.aid = a.id
WHERE
a.qid = 7
AND u.id = a.uid
GROUP BY
a.`right` DESC

Gathering multiple fields

$q = "SELECT s.id, s.title, s.description,
(SELECT COUNT(*) FROM ".FORUM_THREADS." t WHERE t.cat_id = s.id) AS topics,
(SELECT COUNT(*) FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
WHERE t.cat_id = s.id) AS replies,
(SELECT r.date FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
FROM ".FORUM_SUBCATEGORIES." s WHERE s.parent = '$catid' AND s.status = '0' ORDER BY s.id";
I am attempting to select more than one field on the following part of the query
(SELECT r.date FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
INNER JOIN ".TBL_USERS." u ON u.id = r.author WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
Along with r.date, I want to select u.username and r.author.
How can I go about doing this?
Thanks!
Just add them to the SELECT:
(SELECT r.date, r.author, u.username FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
INNER JOIN ".TBL_USERS." u ON u.id = r.author WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
UPDATED after comment from OP:
You need to do 3 separate selects OR (depending on your data model) change the query so that the last_post query ends up after/in the FROM clause (there it can have as many columns as you want)...
Luke, you have a central select statement which uses nested select statements for getting the count. You can't depend on the nested select statements to count as the inner join, so you're going to have to add them to the central select statement instead.
In other words, join ".FORUM_REPLIES." and "u" (not sure what that's supposed to represent) with ".FORUM_SUBCATEGORIES.". I'd write the query for you, but I don't know how to link subcategories with replies and subcategories with u.