SQL sub query WHERE last of id - mysql

Trying my first sub query and cant seem to get the right syntax, tried many variations, not sure if i should use temp table or not. Im using this as a guide:
Source
#1064 - 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 'WHERE log.user_id = 16)AS tempTable' at line 11
SQL
UPDATE log
SET log.out_datetime = NOW()
WHERE log.log_id IN
(
SELECT log_id FROM
(
SELECT log.log_id
FROM log
ORDER BY log.log_id DESC
LIMIT 1
WHERE log.user_id = 16 //<- line 11
)
AS tempTable
)

Your statements are out of order. Also, you don't need IN, you can just use =.
More importantly, you don't need a subquery at all, because MySQL supports ORDER BY and LIMIT in UPDATE queries:
UPDATE log
SET log.out_datetime = NOW()
WHERE log.user_id = 16
ORDER BY log.log_id DESC
LIMIT 1;

It should be change as below.
Correct SQL syntax:
SELECT field-names FROM table-name WHERE field-name=value ORDER BY field-name DESC LIMIT number-of-result
UPDATE log
SET log.out_datetime = NOW()
WHERE log.log_id IN
(
SELECT log_id FROM
(
SELECT log.log_id
FROM log
WHERE log.user_id = 16
ORDER BY log.log_id DESC
LIMIT 1
)
AS tempTable
)

Try the code below. WHERE should come before the LIMIT or ORDER BY clause --
UPDATE log
SET log.out_datetime = NOW()
WHERE log.log_id IN
(
SELECT log.log_id
FROM log
WHERE log.user_id = 16
ORDER BY log.log_id DESC
LIMIT 1
)

Related

How to check if id occurs in other table in MySQL

I have a table an_visit that has column visit_id. There is also a table an_transaction that has some visit_id too.
I would like to get a new column in MySQL based on if visit_id occurs in both tables. My approach:
SELECT visit_id, datetime_add, ISNULL((SELECT
1
FROM an_transaction
WHERE an_transaction.visit_id = an_visit.visit_id), 0)
FROM an_visit
WHERE datetime_add >= '2021-08-01'
LIMIT 50
But I got this error: MySQLdb.OperationalError: (1582, "Incorrect parameter count in the call to native function 'ISNULL'"). What do I do wrong, please?
SELECT visit_id, datetime_add, ISNULL((SELECT
1
FROM an_transaction
WHERE an_transaction.visit_id = an_visit.visit_id limit 1))
FROM an_visit
WHERE datetime_add >= '2021-08-01'
LIMIT 50
OR
SELECT visit_id, datetime_add, IFNULL((SELECT
1
FROM an_transaction
WHERE an_transaction.visit_id = an_visit.visit_id limit 1),0)
FROM an_visit
WHERE datetime_add >= '2021-08-01'
LIMIT 50

MySQL Query from version 5.1 is not working in 5.7

select * from batches join (
select * from (
select *, row_number() over (
partition by batch_id
order by date ASC
) as row_num
from batch_schedule where display = 'Yes'
) as d_schedule
where d_schedule.row_num = 1
)
as f_schedule
on batches.id = f_schedule.batch_id
WHERE (f_schedule.date BETWEEN '2021/03/01' AND '2021/04/30')
This query is working fine in version 5.1 but not working in 5.7
What I am trying to achieve is,
filtering batches based on batch_schedule start dates.
I need to select the 1st row from the right table with condition display = 'Yes' and order by date asc and based on that row value i need to display batches.
I am getting the below error message
select is not valid at this position for this server version expecting '(' with
select * from batches join ( SELECT * from batch_schedule
where display = 'Yes' group by batch_id order by date asc )
as f_schedule on batches.id = f_schedule.batch_id
where(f_schedule.date BETWEEN '2021/03/01' AND '2021/04/30');
I tried this and it works.
I am posting here in case if someone looking for the same thing it will help.

SQL query with a major NOT IN not working

Does anyone know what's wrong with this query?
This works perfectly on its own:
SELECT * FROM
(SELECT * FROM data WHERE site = '".$id."'
AND disabled = '0'
AND carvotes NOT LIKE '0'
AND (time > ( now( ) - INTERVAL 14 DAY ))
GROUP BY car ORDER BY carvotes DESC LIMIT 0 , 10)
X order by time DESC
So does this:
SELECT * FROM data WHERE site = '".$id."' AND disabled = '0' GROUP BY car DESC ORDER BY time desc LIMIT 0 , 30
But combining them like this:
SELECT * FROM data WHERE site = '".$id."' AND disabled = '0' AND car NOT IN (SELECT * FROM
(SELECT * FROM data WHERE site = '".$id."'
AND disabled = '0'
AND carvotes NOT LIKE '0'
AND (time > ( now( ) - INTERVAL 14 DAY ))
GROUP BY car ORDER BY carvotes DESC LIMIT 0 , 10)
X order by time DESC) GROUP BY car DESC ORDER BY time desc LIMIT 0 , 30
Gives errors. Any ideas?
Please try the following...
$result = mysqli_query( $con,
"SELECT *
FROM data
WHERE site = '" . $id .
"' AND disabled = '0'
AND car NOT IN ( SELECT car
FROM ( SELECT car,
carvotes
FROM data
WHERE site = '" . $id .
"' AND disabled = '0'
AND carvotes NOT LIKE '0'
AND ( time > ( NOW( ) - INTERVAL 14 DAY ) )
GROUP BY car
ORDER BY carvotes DESC
LIMIT 10 ) X
)
GROUP BY car
ORDER BY time DESC
LIMIT 30" );
The main cause of your problem is that with car NOT IN ( SELECT * FROM ( SELECT *... you are trying to compare each record's value of car with each row returned by your subquery. IN requires you to have the same number of fields on both sides of the comparison. By using SELECT * at both levels of the subquery you were ensuring that the right side of the comparison had however many fields are in data versus your single field on the left, which confused MySQL.
Since you are aiming to compare to a single field, namely car, our subquery has to select just the car field from its dataset. Since the sort order of the subquery's results has no effect upon the IN comparison, and since our innermost query will be returning just car, I have removed the outer level of the subquery.
Beyond changing the first part of the subquery to SELECT car, the only other change that I have made to the subquery is to change LIMIT 0, 10 to LIMIT 10. The former means limit to the the 10 records that are offset by 0 from the first record. This is useful if you want records 6 to 15, but redundant for 1 to 10 as LIMIT 10 has the same affect and is slightly simpler. Ditto for LIMIT 0, 30 at the end of your overall statement.
As for the main body of the statement, I have not made any attempt to specify what fields (or aggregate functions of those fields) should be returned since you have made no statement indicating what your requirements / preferences are. If you are satisfied that GROUP BY has left you with a still valid set of values, then all the good, but if not then I recommend that you rewrite your Question to be specific about that detail.
By default, MySQL sorts the data subjected to a GROUP BY into ascending order, but if an ORDER BY clause is also present then it overrides the GROUP BY's sort pattern. As such, there is no benefit to specifying DESC after either of your GROUP BY car clauses, so I have removed it where it occurs.
Interesting Sidenote : You can override a GROUP BY's sort by specifying ORDER BY NULL.
If you have any questions or comments, then please feel free to post a Comment accordingly.
Further Reading
https://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html - on optimising your ORDER BY sorting
https://dev.mysql.com/doc/refman/5.7/en/select.html - on the SELECT statement's syntax - specifically the parts to do with LIMIT.
https://www.w3schools.com/php/php_mysql_select_limit.asp - a simpler explanation of LIMIT
This is your query:
SELECT *
FROM data
WHERE site = '".$id."' AND disabled = '0' AND
car NOT IN (SELECT *
FROM (SELECT *
FROM data
WHERE site = '".$id."' AND
disabled = '0' AND
carvotes NOT LIKE '0' AND
(time > ( now( ) - INTERVAL 14 DAY ))
GROUP BY car
ORDER BY carvotes DESC
LIMIT 0 , 10
) x
ORDER BY time DESC
)
GROUP BY car DESC
ORDER BY time desc
LIMIT 0 , 30 ;
Several comments:
Do not wrap integer constants in single quotes. This can mislead people. This can mislead optimizers.
Do not use string functions on integers (such as like). Same reason.
NOT IN with subqueries is dangerous. The construct does not handle NULL values the way you expect. Use NOT EXISTS or LEFT JOIN instead.
When using subqueries, ORDER BY is almost never appropriate.
Never use SELECT * with GROUP BY. It is just wrong. Happily, MySQL 5.7 has changed its defaults to reject this anti-pattern
So, a better way to write this query is something like this:
SELECT d.car, MAX(time) as time
FROM data d LEFT JOIN
(SELECT d2.*
FROM data d2
WHERE d2.site = '".$id."' AND
d2.disabled = 0 AND
d2.carvotes NOT LIKE 0 AND
(d2.time > ( now( ) - INTERVAL 14 DAY ))
GROUP BY d2.car
ORDER BY carvotes DESC
LIMIT 0 , 10
) car10
ON d.car = car10.car
WHERE d.site = '".$id."' AND d.disabled = 0' AND
car10.car IS NOT NULL
GROUP BY car DESC
ORDER BY MAX(time) desc
LIMIT 0 , 30 ;
Alternatively, use SELECT * and remove the GROUP BY in the outer query.

Mysql time difference UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timestamp)

My current sql statement is like follows..
SELECT * FROM `Main`
WHERE username = '$username'
AND fromsite = '$website'
ORDER BY `votes`.`timestamp` DESC
LIMIT 0 , 1
however the timestamp column shows a timestamp like " "2014-03-19 12:00:43" ...Following another question I had an answer along the lines of using ...
SELECT UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timestamp) AS seconds_ago
However not great with mysql and still don't see how I can still use the original select statement and work in a function like above, so that converts the timestamp column and shows as seconds ago instead.
Just ditch the * and list the columns and expressions you want returned.
SELECT m.username
, m.fromsite
, m.timestamp
, UNIX_TIMESTAMP()-UNIX_TIMESTAMP(m.timestamp) AS seconds_ago
, m.votes
FROM `Main` m
WHERE m.username = '$username'
AND m.fromsite = '$website'
ORDER BY m.votes, m.timestamp DESC
LIMIT 0,1

Mysql Syntax Error when running as prepared statment

I've this stored procedure in which I am using a prepared statment to perform two queries.Here's the procedure.
SET #uid = puserid;
SET #rangee = plimit * 50;
SET #post = 'post';
PREPARE STMT FROM
'
SELECT notifications.postid,victims.victimid,friends.friendsname,notificationrecievers.status
FROM friends,victims,notifications,notificationrecievers
WHERE victims.postid=notifications.postid
AND notificationrecievers.notificationid=notifications.notid
AND notificationrecievers.recieverid=?
AND notifications.type=?
AND friends.friendsid=victims.victimid
AND notificationrecievers.notificationid <=
(
SELECT MAX(notid) FROM
(
SELECT n.notid FROM user u,notifications n,notificationrecievers nr WHERE
nr.recieverid=? AND u.userid=n.senderid AND nr.notificationid=n.notid ORDER BY n.notid DESC
LIMIT 50 OFFSET ?
)a
)
AND notificationrecievers.notificationid >=
(
SELECT MIN(notid) FROM
(
SELECT n.notid FROM user u,notifications n,notificationrecievers nr WHERE
nr.recieverid=? AND u.userid=n.senderid AND nr.notificationid=n.notid ORDER BY n.notid DESC
LIMIT 50 OFFSET ?
)b
)
ORDER BY notifications.postid DESC;
UPDATE notificationrecievers
SET notificationrecievers.status=1
WHERE notificationrecievers.status=0
AND notificationrecievers.recieverid=?
AND
notificationrecievers.notificationid <=
(
SELECT MAX(notid) FROM
(
SELECT n.notid FROM user u,notifications n,notificationrecievers nr WHERE
nr.recieverid=? AND u.userid=n.senderid AND nr.notificationid=n.notid ORDER BY n.notid DESC
LIMIT 50 OFFSET ?
)e
)
AND
notificationrecievers.notificationid >=
(
SELECT min(notid) FROM
(
SELECT n.notid FROM user u,notifications n,notificationrecievers nr WHERE
nr.recieverid=? AND u.userid=n.senderid AND nr.notificationid=n.notid ORDER BY n.notid DESC
LIMIT 50 OFFSET ?
)g
);
';
EXECUTE STMT USING #uid,#post,#uid,#rangee,#uid,#rangee,#uid,#uid,#rangee,#uid,#rangee;
When I run this query in the procedure it gives me syntax error.But when I use it directly by giving hard coded values in place of ? than it works fine.Why is this happening? puserid and plimit are the parameters which i pass to this procedure.
This is the error:
Code: 1064
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 ';
UPDATE
notificationrecievers
SET notificationrecievers.st' at line 25