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.)
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 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;
I am trying to query based on these conditions in an orders table,
// This is not an actual query
SELECT *
IF (store_id = 3) THEN ORDER BY WEIGHT DESC,
ELSEIF (STORE_ID = 7) THEN ORDER BY WEIGHT DESC
ELSEIF ORDER BY WEIGHT = DESC
ELSEIF (EQUAL WEIGHT) ORDER BY ORDER_DATE DESC
ELSEIF (EQUAL WEIGHT AND EQUAL ORDER_DATE) ORDER BY STORE_ID DESC
ELSEIF (EQUAL WEIGHT AND EQUAL ORDER_DATE AND EQUAL STORE_ID) ORDER BY
SHIPPING_METHOD DESC
FROM TABLE orders WHERE carrier_name = 'XXX'
This is as far as what I have got,
//Actual query
SELECT id,store_id,weight
FROM orders
WHERE carrier_name = 'XXX'
ORDER BY
IF(store_id = 3,weight,'')DESC,
IF(store_id = 3,order_date,'')DESC,
IF(store_id = 3,store_id,'')DESC,
IF(store_id = 3,shipping_method,'')DESC,
IF(store_id = 7,weight,'')DESC,
IF(store_id = 7,order_date,'')DESC,
IF(store_id = 7,store_id,'')DESC,
IF(store_id = 7,shipping_method,'')DESC,
IF(TRUE,weight,'')DESC,
IF(TRUE,order_date,'')DESC,
IF(TRUE,store_id,'')DESC,
IF(TRUE,shipping_method,'')DESC
The result obtained is
I am not sure why 53.39 and 30.35 are not sorted. What am I doing wrong?
Please suggest if there is a better way to attain this.
This is the required result,
Based on your expected output, the following query should give you what you want:
SELECT *
FROM orders
WHERE carrier_name = 'XXX'
ORDER BY CASE WHEN store_id = 3 THEN 0
WHEN store_id = 7 THEN 1
ELSE 2 END,
store_id,
weight DESC
For an explanation of the logic in the ORDER BY clause, the first condition puts store_id 3 first, followed by 7, followed by everything else. The next conditions orders each of these three groups in ascending order by the store_id. Note that for 3 and 7, this second step will be ignored, because the store_id value is the same for these groups (3 and 7 respectively). Finally, the third condition is to order by the weight in descending order.
ORDER BY
weight DESC, -- as i can see all true in your cases
order_date DESC,
store_id DESC,
shipping_method DESC
I have the following query:
(SELECT ad_code, ad_zone FROM on_ads WHERE ad_zone = 1 AND status = '1' ORDER BY RAND() LIMIT 1) UNION (SELECT ad_code, ad_zone FROM on_ads WHERE ad_zone = 2 AND status = '1' ORDER BY RAND() LIMIT 1);
It's being logged as slow query in my server. I am trying to optimize it. I tried the following query
(SELECT ad_code, ad_zone FROM on_ads WHERE ad_zone = 1 AND status = '1' OR ad_zone = 2 AND status = '1' ORDER BY RAND() LIMIT 2)
But the problem with this query is that the first one was selecting two random rows, one with ad_zone=1 and the other with ad_zone=2. While mine selects two rows, but there is no guarantee it will select two different rows (One with ad_zone=1 and the other with ad_zone=2).
What should I do to optimize this query?
You have to try something like that:
(SELECT DISTINCT(ad_code), ad_zone FROM on_ads WHERE (ad_zone = 1 OR ad_zone = 2) AND status = '1' ORDER BY RAND() LIMIT 2)
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;