MySql if then query - mysql

Is it possible to use if/then statements in mySql? I am looking to check the value of a column in a JOIN table and order the results based on the value of that column.
My sorry attempt:
SELECT t1.*
FROM t1
JOIN t2 ON t1.ID = t2.ID
WHERE t1.ID = '888'
if(t2.col1 = '1') ORDER BY t1.tid ASC
else ORDER BY RAND()

You can use CASE:
ORDER BY
CASE WHEN t2.col1 = 1 THEN t1.tid ELSE rand() END ASC
Beware the performance of this may not be so good, as MySQL won't be able to use an index for the order t1.tid.
You should also be aware that you can order by multiple things, so that possibly this will do what you want:
ORDER BY t1.tid ASC, RAND()
Also, you should keep in mind that ORDER BY RAND() LIMIT 1 will actually fetch every row, calculate a random number for each, sort them, then finally just return the first row. So on data of a reasonable size, it will be slow (and also result in temp tables).

Related

Using `limit` with an update sql query

I have the following query where I want to limit the number of rows it updates for the subs table. It keeps hitting an error though, where am I going wrong?
UPDATE subs t1
INNER JOIN imp_subscriptionlog t2
ON t1.subscription_id = t2.subscription_id
SET t1.cancellation_date = t2.date
WHERE t2.event = 'subscription_cancelled'
LIMIT 35
This is the error:
Incorrect usage of UPDATE and LIMIT
Error code 1221.
LIMIT is allowed in single-table updates only, as explained in the documentation:
For the single-table syntax, [...] if the ORDER BY clause is specified, the rows are updated in the order that is specified. The LIMIT clause places a limit on the number of rows that can be updated.
For multiple-table syntax, ORDER BY and LIMIT cannot be used.
You can rewrite the query to use a correlated subquery instead of a join:
update subs
set cancellation_date = (
select t2.date
from imp_subscriptionlog t2
where t2.subscription_id = subs.subscription_id and t2.event = 'subscription_cancelled'
)
order by ???
limit 35
Notes:
you should be specifying an order by clause in the query, otherwise it is undefined which rows will actually be updated
the query implicitly assumes that there is always just one matching row in imp_subscriptionlog for each row in subs; if that's not the case, then you must order by and limit 1 in the subquery as well, or use aggregation
we can also ensure that there is a match before updating by adding a where clause to the query
Here is a "safer" version of the query, that updates to the maximum date value available in the other table, while not modifying rows that have no match:
update subs
set cancellation_date = (
select max(t2.date)
from imp_subscriptionlog t2
where t2.subscription_id = subs.subscription_id and t2.event = 'subscription_cancelled'
)
where exists (
select 1
from imp_subscriptionlog t2
where t2.subscription_id = subs.subscription_id and t2.event = 'subscription_cancelled'
)
order by ???
limit 35
Update sub1
Inner join
(
//your select statement another table
//condition
//Now use limit
Limit 10
)
On
sub.data = table.date
set

Deleting min value from table

I have a table of 10 high scores, when a new user comes along with a new high score that's greater than the lowest, I want to delete the minimum score from the table. I have tried every suggested way of doing this. Please can someone help.
Something like this should work. You'd run it after inserting the new record.
delete from t t1 where t1.score not in
(select t2.score from t t2 order by t2.score desc limit 10)
If you have a unique ID for each record in the table, then I'd modify it as follows:
delete from t t1 where t1.id not in
(select t2.id from t t2 order by t2.score desc limit 10)
Don't delete from the table -- way too much maintenance involved. Just run the query:
select t.*
from t
order by t.score desc
limit 10;
You can put an index on (score), so this runs faster.
You can encapsulate this in a view.

mysql return multiple columns in subquery for previous and next in same table

I am trying to concoct a mysql query that returns, in a single row, the fields for a given row, as well as a few fields from a row that matches the "previous" position, and the same fields for the "next" position. I'm pretty new at mysql, but for all the scouring the net for answers, this is the best I can do:
SELECT *,
(select id
from mytable t2
where t2.added_on < t.added_on
order by t2.added_on DESC
limit 1
) as prev_id,
(select id
from mytable t3
where t3.added_on > t.added_on
order by t3.added_on
limit 1
) as next_id FROM mytable as t ORDER BY `added_on`
which works, but only gives me the id field for the "previous" and "next". As you may know, using * (or 'id', 'title') instead of id in the subqueries gives an error. I've looked into using JOINs and some other approaches but I'm just simply not getting it.
OK, I figured it out, here is the solution for all of you out there trying to find a solution to this. Make sure to vote up if it helped you.
SELECT t.*,
prev.id as prev_id,
prev.added_on as prev_added_on,
next.id as next_id,
next.added_on as next_added_on
FROM `TABLE_NAME` AS t
LEFT JOIN `TABLE_NAME` AS prev
ON prev.id =
(select id
from `TABLE_NAME` t2
where t2.added_on < t.added_on
order by t2.added_on DESC
limit 1)
LEFT JOIN `TABLE_NAME` AS next
ON next.id =
(select id
from `TABLE_NAME` t3
where t3.added_on > t.added_on
order by t3.added_on
limit 1 )
ORDER BY t.added_on DESC
That last ORDER BY actually causes the whole thing to be greatly optimized for some reason (my current understanding of mysql doesn't let me know why this is for sure) and in my case it makes execution at least twice as fast as without it.

Optimizing a query : joining a table on itself

i want to get last two row of a table in one query as new data and previous data
i got
select tbl.x , tbl2.x as last_x
from tbl left join tbl tbl2 ON tbl.id!= tbl2.id
order by tbl.id desc , tbl2.id desc limit 1
it works fine but i think it might get slow in a big DB
is there any way to make this faster ?
A LIMIT should work in a basic subquery, and so the following will possibly be more efficient
SELECT Sub1.x , Sub2.x as last_x
FROM (SELECT x FROM tbl ORDER BY tbl.id DESC LIMIT 1) Sub1
CROSS JOIN (SELECT x FROM tbl ORDER BY tbl.id DESC LIMIT 2, 1) Sub2
You can take a look at the execution plan and try to optimize your query, but usually you do this when you face a problem so you can determine which parts are taking long.
Chick this thread to: How to optimise MySQL queries based on EXPLAIN plan
But as saied i would not try to solve a problm which still does not exist, i do not actually see a problem aith your query.

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