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;
Related
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'
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.)
I am trying to change 'from_user' with a parameter from the other table and it doesn't work but when I am using the same table it works like a charm:
SELECT from_user, message_contents, message_read, to_user, date
FROM table1
WHERE date IN (
SELECT MAX( date )
FROM table1
WHERE to_user = 1 GROUP BY from_user
)
ORDER BY from_user ASC , date DESC
but this one just show one record but not all latest ones:
SELECT table2.`display_name`, message_contents, message_read, to_user, date
FROM table1, table2
WHERE table1.`from_user` = table2.`ID`
AND date IN ( SELECT MAX( date )
FROM table1
WHERE to_user = 1 GROUP BY from_user
)
ORDER BY from_user ASC , date DESC
Can anybody help to change 'from_user' with table2.display_name parameter but to get all recent records from mySQL?
You are joining two tables on table1.from_user = table2.id
So, if you don't want that table two to affect the number of rows than you can make a query like this:
SELECT
table1.from_user,
table2.`display_name`,
message_contents,
message_read,
to_user,
date
FROM table1
LEFT JOIN table2 ON table1.`from_user` = table2.`ID`
WHERE
date IN (SELECT MAX(date) FROM table1 WHERE to_user = 1 GROUP BY from_user)
ORDER BY from_user ASC , date DESC
I added also table1.from_user on the select clause which will help you see the from users which don't have a display name.
Here's my MySQL query and what it returns:
SELECT email, COUNT(*) AS num
FROM collectors_users
WHERE subscribed != 'NO'
AND lastLogin IS NULL
GROUP BY email
ORDER BY dateadded DESC;
I only want to return results where num > 1. I tried to change my query like this but it doesn't work saying that num is not a recognized column:
SELECT email, COUNT(*) AS num
FROM collectors_users
WHERE subscribed != 'NO'
AND lastLogin IS NULL
AND num > 1
GROUP BY email
ORDER BY dateadded DESC;
How can I return results where num > 1?
After the GROUP BY clause, and before the ORDER BY clause add this:
HAVING COUNT(*) > 1
The HAVING clause gets applied nearly last in the execution plan, after all of the rows have been prepared, prior to the LIMIT clause. This is most useful for conditions that can't be checked while rows are being accessed, but only after the rows have been accessed, such as an aggregate function like a COUNT(*), though it can be used for non-aggregates.
I think you should use HAVING
SELECT email, COUNT(*) AS num
FROM collectors_users
WHERE subscribed != 'NO'
AND lastLogin IS NULL
GROUP BY email
ORDER BY dateadded DESC
HAVING COUNT(*) > 1;
this question can help you to understand why HAVING and not WHERE
WHERE vs HAVING
SELECT email, COUNT(*) as num
FROM collectors_users
WHERE subscribed != 'NO'
AND lastLogin IS NULL
GROUP BY email
HAVING COUNT(*) > 1
Use HAVING clause. Or another way:
SELECT * FROM
(SELECT email, COUNT(*) AS num
FROM collectors_users
WHERE subscribed != 'NO'
AND lastLogin IS NULL
GROUP BY email
ORDER BY dateadded DESC;
) T
WHERE num>1
You can use Having clause.
SELECT email, COUNT(*) AS num
FROM collectors_users
WHERE subscribed != 'NO'
AND lastLogin IS NULL
GROUP BY email
HAVING count(*) > 1
ORDER BY dateadded DESC;
for more information: http://www.w3schools.com/sql/sql_having.asp
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;