ORDER BY breaking mysql query - php

Someone on here helped put together this extremely useful query!
SELECT * FROM results r
INNER JOIN categories c on r.id = c.result_id
WHERE c.name in ('$purpose', '$prop_type', '$loan_type')
GROUP BY r.id
HAVING COUNT(c.c_id) = 3
LIMIT 50 OFFSET 0
Which is working great! However, when I try to order the results by using
SELECT * FROM results r
INNER JOIN categories c on r.id = c.result_id
WHERE c.name in ('$purpose', '$prop_type', '$loan_type')
ORDER BY r.usefulness DESC
GROUP BY r.id
HAVING COUNT(c.c_id) = 3
LIMIT 50 OFFSET 0
I get a syntax error. Am I missing something obvious here?
Thanks a lot!

there is an order for the parts of the query, and ORDER BY should be in the end (before the LIMIT and the OFFSET... try this:
SELECT * FROM results r
INNER JOIN categories c on r.id = c.result_id
WHERE c.name in ('$purpose', '$prop_type', '$loan_type')
GROUP BY r.id
HAVING COUNT(c.c_id) = 3
ORDER BY usefulness DESC
LIMIT 50 OFFSET 0
also make sure that you have spaces in the end of any row...
notice that in mysql that is a shortened version for LIMIT x OFFSET y - you can just write LIMIT y,x

ORDER BY has to come after the HAVING.

Related

Take results within two dates

I have tried various solutions here on the site but unfortunately I did not succeed. I would need that this query that already takes the results with the highest value of the field "vote_up", could also take a second additional value. It picks up the results within a given date (posted_date), a start date and a finish date.
SELECT *
FROM stories S
LEFT JOIN categories C
ON C.category_id = S.c_id
LEFT JOIN (SELECT voted_story,
voter_ip
FROM votes
WHERE voter_ip = '$ip_address'
GROUP BY voted_story) V
ON V.voted_story = S.story_id
WHERE S.story_active = 1
ORDER BY S.vote_up DESC
LIMIT 0, 16
Adding just for clarification, my difficulty is the syntax that makes me errors especially I do not know how to insert two "where" in the same query.
You can add additional WHERE condition clauses for checking posted date as-well.
SELECT *
FROM stories S
LEFT JOIN categories C
ON C.category_id = S.c_id
LEFT JOIN (SELECT voted_story, voter_ip
FROM votes
WHERE voter_ip = "$ip_address"
GROUP BY voted_story) V
ON V.voted_story = S.story_id
WHERE
S.story_active = 1 AND
S.posted_date > "$startDate" AND
S.posted_date < "$endDate"
ORDER BY S.vote_up DESC
LIMIT 0, 16

SQL query is taking a long time to execute

I have researched other questions and tried their solutions, but none helped me. How can I lower the execution time of this query?
SELECT c.id,c.title,c.time,u.username, (SELECT time FROM comments_read as io WHERE io.id=c.id AND io.uid=$logged_userid LIMIT 1) as read_time
FROM comments as c
LEFT JOIN users u ON u.uid=c.uid
WHERE c.deleted=0
ORDER by c.time DESC
LIMIT 20
Thank you so much.
This is your query:
SELECT c.id, c.title, c.time, u.username,
(SELECT io.time
FROM comments_read as io
WHERE io.id = c.id AND
io.uid = $logged_userid
LIMIT 1
) as read_time
FROM comments as c LEFT JOIN
users u
ON u.uid = c.uid
WHERE c.deleted = 0
ORDER by c.time DESC
LIMIT 20;
Indexes can be used to improve performance. I would start with comments(deleted, time, uid, id), users(uid), and comments_read(id, uid, time).
Note: using LIMIT without an ORDER BY is usually discouraged, because the results are unstable. You can get any matching row.
EDIT:
If the above indexes do not help, they might be getting confused by the JOIN. You can do the same thing as:
SELECT c.id, c.title, c.time,
(SELECT u.username FROM users u WHERE u.uid = c.uid) as username,
(SELECT io.time
FROM comments_read as io
WHERE io.id = c.id AND
io.uid = $logged_userid
LIMIT 1
) as read_time
FROM comments as c
WHERE c.deleted = 0
ORDER by c.time DESC
LIMIT 20;
This should take advantage of the above indexes and have no "file sort" step to slow things down.

mysql limit not work orderby with limit 0,5

$selectorders=sprintf("SELECT s.stud_rollno, s.admissiondate, s.fname, s.lname, s.gender, c.communityname, t.name, y.yearname, s.iname
FROM erp.student s inner join year y
on year_id = s.ayear
inner join community c
on c.d_id = s.community
inner join types t
on t.id = s.department
ORDER BY s.stud_rollno
limit 0,10");
$results = mysql_query($selectorders) or die(mysql_error());
$tot_rsselect = mysql_num_rows($results);
my runtime error is
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 0, 200' at line 1
but run in localhost/phpmyadmin page.
I think you are trying to select only top 10 rows. So in this scenario there is no need to use 0, 10 or like somthing. You can just simply write LIMIT 10
So your query will be:-
"SELECT s.stud_rollno, s.admissiondate, s.fname, s.lname, s.gender, c.communityname, t.name, y.yearname, s.iname
FROM erp.student s inner join year y
on year_id = s.ayear
inner join community c
on c.d_id = s.community
inner join types t
on t.id = s.department
ORDER BY s.stud_rollno
limit 10";
I'm not sure but this might be your solution.

Two seemingly identical queries returning different results when using count (pagination)

I am running two queries to my database for pagination reasons. As such, each query is nearly identical. My COUNT(*) query is not returning the number of results that the non-count query is. I'm baffled as to why this is the case. The queries are below.
SELECT p.host_id, p.rating_support, p.rating_tech, MAX(p.rating_overall) AS rating_overall, p.publish_rating, h.name, prices.price, prices.term_duration
FROM plans p
INNER JOIN hosts AS h ON h.id = p.host_id
INNER JOIN (SELECT plan_id, price, term_duration FROM prices WHERE price > 0 AND price < 50 AND term_duration = 1) prices ON prices.plan_id = p.id
WHERE p.published = 1 AND h.published = 1
GROUP BY p.host_id
ORDER BY rating_overall desc LIMIT 0, 12
SELECT COUNT(*) AS count
FROM plans p
INNER JOIN hosts AS h ON h.id = p.host_id
INNER JOIN (SELECT plan_id, price, term_duration FROM prices WHERE price > 0 AND price < 50 AND term_duration = 1) prices ON prices.plan_id = p.id
WHERE p.published = 1 AND h.published = 1
GROUP BY p.host_id
I'm not an expert at MySQL. Besides the count not providing the correct number of results, the non-count query works perfectly.
Any light on this problem would be great.
With the help of Dems' comment (hunt down and upvote him somewhere :), I created this query. Notice that I removed the subquery, because it seemed unnecessary:
SELECT
COUNT( DISTINCT p.host_id )
FROM plans p
INNER JOIN hosts h ON h.id = p.host_id
INNER JOIN prices ON prices.plan_id = p.id
AND prices.price > 0
AND prices.price < 50
AND prices.term_duration = 1
WHERE p.published = 1
AND h.published = 1
My original answer:
To get the number of total row, you have to wrap the GROUP BY query into an outer SELECT:
SELECT COUNT(*)
FROM (
SELECT NULL -- we are just counting, so we need no actual data -> a bit faster
FROM plans p
INNER JOIN hosts h ON h.id = p.host_id
INNER JOIN prices ON prices.plan_id = p.id
AND prices.price > 0
AND prices.price < 50
AND prices.term_duration = 1
WHERE p.published = 1
AND h.published = 1
GROUP BY p.host_id
) AS all_rows_without_data
Or you could use SQL_CALC_FOUND_ROWS + FOUND_ROWS()
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows
A SELECT statement may include a LIMIT clause to restrict the number
of rows the server returns to the client. In some cases, it is
desirable to know how many rows the statement would have returned
without the LIMIT, but without running the statement again. To obtain
this row count, include a SQL_CALC_FOUND_ROWS option in the SELECT
statement, and then invoke FOUND_ROWS() afterward:
First, simply select the required rows, but add SQL_CALC_FOUND_ROWS:
SELECT SQL_CALC_FOUND_ROWS
p.host_id, p.rating_support, p.rating_tech,
MAX(p.rating_overall) AS rating_overall,
p.publish_rating, h.name, prices.price, prices.term_duration
FROM plans p
INNER JOIN hosts AS h ON h.id = p.host_id
INNER JOIN prices ON prices.plan_id = p.id
AND prices.price > 0
AND prices.price < 50
AND prices.term_duration = 1
WHERE p.published = 1 AND h.published = 1
GROUP BY p.host_id
ORDER BY rating_overall desc
LIMIT 0, 12;
Second, get the number of rows that would have been returned if there weren't a LIMIT statement in the first query:
SELECT FOUND_ROWS();
Update: SQL_CALC_FOUND_ROWS + FOUND_ROWS() doesn't seem very reliable, always returs zero for unknown reason (not just me: FOUND_ROWS() keeps returning 0 ):
http://sqlfiddle.com/#!2/7304d/8
The result of your second query would return the same number of rows, but the first row won't give you back the total.
The results would give the count for each group per row:
3
5
1
6
etc.
etc.
To get the result into one row, use COUNT(DISTINCT p.host_id) or array_sum() in PHP on the full result set.

MySQL Query Multiple LEFT Joins problem

I am trying to get the required result from the following query but it doesnt seem to work...
SELECT DISTINCT
u.user_name as user_name,
u.total_points as total_points,
u.user_id as user_id,
COUNT(a.id) as user_total_articles_published,
COUNT(r.id) as user_total_replies_published,
COUNT(v.id) as user_total_votes_done
FROM users as u
LEFT JOIN articles as a ON u.user_id=a.user_id
LEFT JOIN replies as r ON u.user_id=r.user_id
LEFT JOIN votes as v ON u.user_id=v.user_id
GROUP BY u.user_id
ORDER BY u.total_points DESC
LIMIT 10
If i remove the last 2 LEFT jOINS the query will work... whats wrong with the other 2? Do i have to use another method for this to work?
thanks
I think by 'not working' you mean that the query returns too many records? That is because of the combination of joins. You return each reply for each article record, so the numbers are multiplied. You can solve this by using DISTINCT in the COUNT. That way, you count the unique id's, so you count each article only once:
COUNT(distinct a.id) as user_total_articles_published,
COUNT(distinct r.id) as user_total_replies_published,
COUNT(distinct v.id) as user_total_votes_done
[edit]
A possibly faster solution, eliminating the need for DISTINCT and GROUP BY:
SELECT
u.user_name as user_name,
u.total_points as total_points,
u.user_id as user_id,
(SELECT COUNT(a.id) FROM articles a
WHERE a.user_id = u.user_id) as user_total_articles_published,
(SELECT COUNT(r.id) FROM replies r
WHERE r.user_id = u.user_id) as user_total_replies_published,
(SELECT COUNT(v.id) FROM votes v
WHERE v.user_id = u.user_id) as user_total_votes_done
FROM users as u
ORDER BY u.total_points DESC
LIMIT 10

Categories