Join statement...how do do ORDER BY? - mysql

I have the following LEFT JOIN statement (though probably also applies to even a simpler SELECT statement):
SELECT * FROM t1 LEFT JOIN t2 ON t2.c = t1.c WHERE t1.m LIKE 'captain%' GROUP BY
t1.c ORDER BY t2.date DESC LIMIT 0,10
The results get returned but they are not ordered by t2.date DESC...I imagine this is due to having the GROUP BY statement in there. How can I group the results AND order them?
thx

Put your query in a subquery and then use ORDER BY.
SELECT *
FROM
(SELECT *
FROM t1 LEFT JOIN t2 ON t2.c = t1.c
WHERE t1.m LIKE 'captain%'
GROUP BY t1.c DESC LIMIT 0,10) l1
ORDER BY date

In normal SQL it would not even be allowed to ORDER BY t2.date because you aren't grouping on it and you are not using an aggregate function on it, so you can't select it.
Anyway, as MySQL just picks values from the rows in an undefined manner and afterwards sorts them, the t2.date column in your results should be sorted. Please show some actual output.

Related

MySQL: LIMIT parameter in JOIN producing unexpected results

I have read here that MySQL processes ordering before applying limits. However, I receive different results when applying a LIMIT parameter in conjunction with a JOIN subquery. Here is my query:
SELECT
t1.id,
(t2.counts / c.matches)
FROM
table_one t1
JOIN
table_two t2 ON t1.id = t2.id
JOIN
(
SELECT
t1.id, COUNT(DISTINCT t1.id) AS matches
FROM
table_one t1
JOIN table_two t2 ON t1.id = t2.id
WHERE
t1.id IN (3390 , 3236, 148, 2811, 829, 137)
AND t2.value_one <= 30
AND t2.value_two < 2
GROUP BY t1.id
ORDER BY (t2.counts / matches)
LIMIT 0, 50 -- PROBLEM IS HERE (I think)
) c ON c.id = t1.id
ORDER BY (t2.counts / c.matches), t1.id;
Here is a rough description of what I think is happening:
The sub-query selects a bunch of ids from table_one that meet the criteria
These are ordered by (t2.counts / matches)
The top 50 (in ascending order) are fashioned into a table
This resulting table is then joined on the the id column
Results are returned from the top level JOIN - without a GROUP BY clause this time. table_one is a reference table so this will return many rows with the same ID.
I appreciate that some of these joins don't make a lot of sense but I have stripped down my query for readability - it's normally quite chunky .
The problem is that when, I include the LIMIT parameter I get a different set of results and not just the top 50. What I want to do is get the top results from the subquery and use these to join onto a bunch of other tables based on the reference table.
Here is what I have tried so far:
LIMIT on the outer query (this is undesirable as this cuts off important information).
Trying different LIMIT tables and values.
Any idea what is going wrong, or what else I could try?
I have found a solution to my problem. It seems as if my matches column name does can't be used in my ORDER BY clause - which is weird since I don't get an error. Either way, this solves the problem:
SELECT
t1.id,
(t2.counts / c.matches)
FROM
table_one t1
JOIN
table_two t2 ON t1.id = t2.id
JOIN
(
SELECT
t1.id, COUNT(DISTINCT t1.id) AS matches
FROM
table_one t1
JOIN table_two t2 ON t1.id = t2.id
WHERE
t1.id IN (3390 , 3236, 148, 2811, 829, 137)
AND t2.value_one <= 30
AND t2.value_two < 2
GROUP BY t1.id
ORDER BY (t2.counts / COUNT(DISTINCT t1.id)) -- This line is changed
LIMIT 0, 50
) c ON c.id = t1.id
ORDER BY (t2.counts / c.matches), t1.id;

Can I use 1 instead of asterisk for SQL_CALC_FOUND_ROWS?

Here is my query:
SELECT t1.mycol
FROM mytable t1
JOIN mytable t2
ON t1.id = t2.postid
ORDER BY value
LIMIT 10;
It works well.
Now I need to count the number of matched rows without the limitation. So I have've added this SQL_CALC_FOUND_ROWS * to the select statement and my query throws:
value is ambiguous in the order by clause.
Why? And how can I fix it?
Noted that, when I use SQL_CALC_FOUND_ROWS 1 instead of SQL_CALC_FOUND_ROWS * in the select statement, then apperantly all fine. So, is it ok to use SQL_CALC_FOUND_ROWS 1? (I'm asking this because that's SQL_CALC_FOUND_ROWS * in the documentation).
I'm not sure why you are using a self-join, but you say the query does what you want.
Your problem is simply the lack of a qualified column name in the order by. It has nothing to do with SQL_CALC_FOUND_ROWS:
SELECT SQL_CALC_FOUND_ROWS t1.mycol
FROM mytable t1 JOIN
mytable t2
ON t1.id = t2.postid
ORDER BY t1.value
LIMIT 10;
I do not know why your original query would have worked. It has the same ambiguous column name in the ORDER BY.
Give it a try:
SELECT SQL_CALC_FOUND_ROWS * from mytable t1
JOIN mytable t2
ON t1.id = t2.postid
ORDER BY t1.value
LIMIT 10;
SELECT FOUND_ROWS();
The reason why you got the error was that, you are joining table with itself, so obviously, every column would occur twice. That's why the name is ambiguous. I added quelifier t1.
Try this
SELECT SQL_CALC_FOUND_ROWS t1.* from mytable t1
JOIN mytable t2
ON t1.id = t2.postid
ORDER BY t1.value
LIMIT 10;
SELECT FOUND_ROWS();

MySQL aliased subquery cannot be used in where clause

I have a query given below that returns all the data asked. Then in the next query I need to write I need to restrict the output to where the subquery is greater than 5.
I will show examples but I cannot understand why I cannot do what I am attempting.
Query without restriction
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
order by Times_Checked_Out desc, t1.BOOK_TITLE;
Screenshot of output
Attempt at query with restrictions
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
where Times_Checked_Out > 5
order by Times_Checked_Out desc, t1.BOOK_TITLE;
Error
You can't use a derived column in a where clause, need to use HAVING:
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
HAVING Times_Checked_Out > 5
order by Times_Checked_Out desc, t1.BOOK_TITLE;

MySQL correlated subquery SUM() ORDER BY

Is there anyway to optimize the following query:
SELECT
t1.id,
(SELECT SUM(col1) FROM table_name_two t2 WHERE t2.name LIKE CONCAT('%',t1.name)) AS col1_count
FROM
table_name_one t1
ORDER BY
col1_count DESC
Using ORDER BY col1_count DESC takes a long time.
Thanks.
Just make a normal join with your comparison in the join's on clause:
SELECT
t1.id,
SUM(t2.col1) AS col1_count
FROM table_name_one t1
LEFT JOIN table_name_two t2 on t2.name LIKE CONCAT('%', t1.name)
GROUP BY 1
ORDER BY 2 DESC
It should be way faster this way - it's basically one query instead of "n" queries, although it won't get any help from indexes using the LIKE operator with a leading %

Mysql limit function doesn't seem to work for me

Here is my query,
select t1.dSyllabus_id,t1.dBatch,t1.dFilePathName,
t2.dDegreeName,t3.dDepartmentAbbr
from tbl_syllabus as t1
join tbl_degree_master as t2,
tbl_department_master as t3
where t2.dDegree_id=t1.dDegree_id
and t3.dDepartment_id=t1.dDepartment_id
and t1.dCollege_id='1'
and t1.dIsDelete='0'
and i get
Without Limit http://img534.imageshack.us/img534/2165/withoutlimi.jpg
applying limit ,
select t1.dSyllabus_id,t1.dBatch,t1.dFilePathName,
t2.dDegreeName,t3.dDepartmentAbbr
from tbl_syllabus as t1
join tbl_degree_master as t2,
tbl_department_master as t3
where t2.dDegree_id=t1.dDegree_id
and t3.dDepartment_id=t1.dDepartment_id
and t1.dCollege_id='1'
and t1.dIsDelete='0'
limit 0,5
i get ,
With Limit http://img13.imageshack.us/img13/2470/withlimit.jpg
I dont get the first five records why?
You get 5 records, but you haven't set an order. They will not come back in a specific order unless you tell them too. In your case I believe you want them in order of their id. Add something like:
order by `t1`.`dSyllabus_id` ASC
So your query looks like:
select t1.dSyllabus_id,t1.dBatch,t1.dFilePathName,
t2.dDegreeName,t3.dDepartmentAbbr
from tbl_syllabus as t1
join tbl_degree_master as t2,
tbl_department_master as t3
where t2.dDegree_id=t1.dDegree_id
and t3.dDepartment_id=t1.dDepartment_id
and t1.dCollege_id='1'
and t1.dIsDelete='0'
order by `t1`.`dSyllabus_id` ASC
limit 0,5
Use ORDER BY
and t1.dIsDelete='0'
ORDER BY 't1.dSyllabus_id'
limit 0,5