Problem in finding next / previous row in mysql - mysql

SELECT id ,MAX(status) AS status FROM Mail WHERE
status < (SELECT status FROM Mail WHERE id = 1000)
GROUP BY status ORDER BY status DESC LIMIT 1;
I am using this query to find the previous row of the current row 1000.Here i am getting NULL values if i use the status column which is not unique.where as it gives proper values if i use unique columns.

Try this:
SELECT m1.id, MAX(m1.status) AS 'status' FROM Mail m1, Mail m2
WHERE m1.status < m2.status AND m2.id = 1000
GROUP BY m1.status ORDER BY m1.status DESC LIMIT 1;

Related

MySQL query to order by time and return n rows after specific id

I have a table in my database (versions: MariaDB 10.3.17, MySQL 5.7) as follows:
id name timestamp
-----------------------------
154875 AXC 154875869
362574 RTB 154875800
962548 MNV 154875969
365847 XRT 154875123
...
what I need:
sort the rows on timestamp descending
then return 24 rows after (below) where id=something
for example for id=962548, the first 3 rows of the expected output will be:
id name timestamp
-----------------------------
154875 AXC 154875869
362574 RTB 154875800
365847 XRT 154875123
how to implement it in MySQL?
Join the query that returns the row with id = something to the table under your conditions:
select t.*
from tablename t
inner join (select * from tablename where id = 365847) c
on t.timestamp < c.timestamp or (t.timestamp = c.timestamp and t.id < c.id)
order by t.timestamp desc, t.id desc
limit 24
but I'm not sure what you mean by below, so maybe you want the opposite order:
select t.*
from tablename t
inner join (select * from tablename where id = 365847) c
on t.timestamp > c.timestamp or (t.timestamp = c.timestamp and t.id > c.id)
order by t.timestamp desc, t.id desc
limit 24
You need to select elements that have the timestamp value greater than your id timestamp, using a query like this:
SELECT *
FROM table
WHERE timestamp>(select timestamp
from table
where id = 'current_id')
ORDER BY timestamp LIMIT 24;
I'd query it something like that:
SELECT * FROM tab
WHERE timestamp >= (SELECT timestamp FROM tab WHERE id = 154875)
AND id <> 154875
ORDER BY timestamp DESC, id DESC
LIMIT 2

Get authorized user now mysql

I have table structure:
I need get last authorized user with status 'Signed in' without last status 'Signed off'. How I can do it?
I have a query:
SELECT * FROM vtiger_loginhistory WHERE status = 'Signed in' ORDER BY login_time DESC LIMIT 1
But this get me last authorized user admin, why? If he is Signed off. I need get Igor, because he is Signed in last.
You can try that: first select more recent row for each username and use JOIN or another SELECT to see if it's a "in" or "off"
EDIT: the concept is the same but corrected thanks to this answer
Version i don't fully understand: https://sqltest.net/#464377
SELECT *
FROM vtiger_loginhistory v_l
LEFT JOIN vtiger_loginhistory tmp
ON (v_l.user_name = tmp.user_name AND v_l.login_time < tmp.login_time)
WHERE tmp.login_time IS NULL AND v_l.status = 'Signed in'
ORDER BY v_l.login_time DESC LIMIT 1
Similar result with a subquery as I described (seems slower as explained in linked answer): https://sqltest.net/#464385
SELECT *
FROM vtiger_loginhistory v_l
INNER JOIN (SELECT user_name, MAX(tmp.login_time) AS maxlogintime
FROM vtiger_loginhistory tmp GROUP BY user_name
ORDER BY login_time DESC) tmp2
ON (v_l.login_time = tmp2.maxlogintime)
WHERE status = 'Signed in'
ORDER BY login_time DESC LIMIT 1
EDITED ORIGINAL NOT WORKING VERSION: (because GROUP BY keeps the first row met, so the oldest dates)
SELECT *
FROM (
SELECT *
FROM vtiger_loginhistory
GROUP BY user_name
ORDER BY login_time DESC
) as temp
WHERE status = 'Signed in'
ORDER BY login_time DESC LIMIT 1
You could check for username that is not IN the list for signed off too
SELECT *
FROM vtiger_loginhistory
WHERE status = 'Signed in'
AND username NOT IN (
select username
from vtiger_loginhistory
where status = 'Signed OFF'
)
ORDER BY login_time DESC LIMIT 1
you can try below way by using not exists
select t1.* from vtiger_loginhistory t1
where
status = 'Signed in'
and not exists ( select 1 from vtiger_loginhistory t2
where t2.user_name=t1.user_name
and status = 'Signed off')
order by STR_TO_DATE(login_time,'%Y%m%d %h%i') DESC LIMIT 1
i think your login_time column is not datetime
There are many Signed in and Signed off user, the admin has signed off but the last signed in is more recent than Igor.
There are 2 solutions for you :
Renew the flow, when user Signed off just update the status instead of create new record
Create top1signedoff temporary table first and select the other not in top1signedoff
CREATE TEMPORARY TABLE top1signedoff SELECT username FROM vtiger_loginhistory WHERE status = 'Signed off' ORDER BY login_time DESC LIMIT 1;
SELECT * FROM vtiger_loginhistory
WHERE status = 'Signed in'
and username Not IN (
SELECT username FROM top1signedoff
)
ORDER BY login_time DESC LIMIT 1
Following query should give you the desired result
SELECT t.login_id,t.user_name, t.logout_time,t.login_time,t.status
FROM vtiger_loginhistory t
WHERE t.login_id = (
SELECT MAX(t2.login_id)
FROM vtiger_loginhistory t2
WHERE t2.user_name = t.user_name
GROUP BY t2.user_name
)
AND t.status = 'Signed in';
What we are doing here..
in sub-query we are fetching last login_id for user
and in main query we are checking if the status for that login_id is 'Signed in'

MySQL clause in where `case when`

I am trying to figure it out but no solution at all.
My query :
SELECT * FROM table
WHERE owner = 'user'
AND (
CASE WHEN status = 'NEW'
THEN status = 'NEW'
ELSE status IN ('CB','NA','NI','GC','FC')
END
)
ORDER BY RAND() DESC
LIMIT 1;
What I want to achieve is to show all records where status is NEW in an Random order limited by one row each, when no records NEW for the user the query needs to show the other statuses.
Thank you.
SELECT * FROM Table
WHERE owner = 'user'
AND (CASE WHEN (SELECT COUNT(*) FROM Table WHERE status = 'NEW') >= 1 THEN
status = 'NEW'
ELSE status IN ('CB','NA','NI','GC','FC')
END)
ORDER BY RAND() DESC
LIMIT 1;
Demo
http://sqlfiddle.com/#!9/09b1c8/1
What i think, you can simply
SELECT * FROM table
WHERE owner = 'user'
AND (
CASE WHEN status = 'NEW'
THEN status = 'NEW'
ELSE status IN ('CB','NA','NI','GC','FC')
END
)
ORDER BY RAND() DESC
LIMIT 1;
To
SELECT * FROM table
WHERE owner = 'user' AND status IN ('NEW','CB','NA','NI','GC','FC')
GROUP By some_id
ORDER BY RAND() DESC
LIMIT 1;
SELECT * FROM table
WHERE owner = 'user'
AND status IN ('NEW', 'CB','NA','NI','GC','FC')
ORDER BY status = 'NEW' DESC,
RAND() DESC
LIMIT 1;
Will give you a total of 1 row, giving preference to a random 'NEW'. If no 'NEW' rows, then a random one of the others.
(Please clarify your Question and provide sample output.)

MySQL UNION on same table with two WHERE clause

I have a table alerts
date | alert | status | sentDate | id
In this table, after I have sent the alert, I set the status to 'sent' and set the sent date. By default the status is 'not' (which means it has not been sent yet).
Now, I want to get the last sentDate, I can get this using the following query
SELECT sentDate FROM alerts WHERE id = someid AND status = 'sent' Order by date desc limit 1;
Also, I want to get the latest alert which has not been sent, I am using this query
SELECT date, alert FROM alerts WHERE id = someid AND status = 'not' order by date asc limit 1;
Is it possible to do this in one query? perhaps using UNION. I have tried to apply UNION/UNION ALL on these two queries but it gives me error.
Can anyone please help?
Thanks in advance.
SELECT
max(CASE WHEN status = 'sent' THEN DATE END) AS sentDate,
max(CASE WHEN status = 'not' THEN DATE END) AS notSentDate
FROM alerts WHERE id = someid
You can try above query.
It will help you.
You Can Try this :
SELECT MAX(t.sentDate) AS sentDate, MAX(t.date) AS date, MAX(alert) AS alert
FROM
(
SELECT MAX(sentDate) AS sentDate, "" AS date, "" AS alert
FROM alerts
WHERE id = someid
AND status = 'sent'
UNION
SELECT "" AS sentDate, date, alert
FROM alerts
WHERE id = someid
AND status = 'not'
) t
You could try this one
SELECT
(Select date from alerts where id= someid AND status='not'
ORDER by date DESC limit 1) latestNotSentDate,
(Select date from alerts where id= someid AND status='sent'
ORDER BY date DESC limit 1) latestSentDate;
The number of columns have to be the same in your queries, try this :
SELECT sentDate,'' FROM alerts WHERE id = 'id' AND status = 'sent' Order by date desc limit 1;
UNION
SELECT date, alert FROM alerts WHERE id = 'id' AND status = 'not' order by date asc limit 1;
In addition, i think the status is irrelevant, this information is given by the presence of a sentDate.
I think you can write :
SELECT sentDate,'' FROM alerts WHERE id = 'id' AND sentDate is not null Order by date desc limit 1;
UNION
SELECT date, alert FROM alerts WHERE id = 'id' AND sentDate is NULL order by date asc limit 1;

Trying to delete the records if greater then 25?

I am trying to delete all records so I only have the last 25 records. I am trying to figure this out but I can't seem to figure out, my MySQL version doesn't support the DELETE LIMIT OFFSET that most suggest, so I am trying to do
DELETE FROM
account_versions
WHERE
account_versions_id < (
SELECT
account_versions_id
FROM
account_versions
ORDER BY
account_versions_id
DESC
LIMIT 24, 1)
AND
account_id = 1
But I can't seem to get it to work. I want to only have the last 25 records for account_id = 1
So, as you said that account_versions_id is an autoincrement. Here is what you need:
DELETE FROM account_versions
WHERE account_id = 1
and account_versions_id IN
(select account_versions_id
from
(SELECT account_versions_id, #id:=#id+1 as rn
FROM account_versions,
( select #id:=0 ) a
ORDER BY account_versions_id DESC) x
where rn > 25)
Now it should work.