I am using NOT IN and also IF in Where Clause of subquery MySQL is it right way?
Working Query:
My query is working and I am also getting the result I desired. I just want to know if I am doing anything wrong because I heard it is not the right way to use IF inside Where Clause but in my case, it is even in a subquery. I have made this query myself. Let me know if there is a better alternative for my query.
Looking for:
I am trying to get all those employees who are not busy between 14:00 & 15:00 where 14:00 and 15:00 is a time coming from input fields(like a search).
SELECT *
FROM `schedule`
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM `schedule`
WHERE ( IF(start_time < '14:00', '14:00', start_time) >= '14:00'
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00')
AND (IF(start_time < '14:00', '14:00', start_time) <= '15:00'
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00')
AND `appoint_date` = '2018-11-30')
mysql sql
|
show 1 more comment
Working Query:
My query is working and I am also getting the result I desired. I just want to know if I am doing anything wrong because I heard it is not the right way to use IF inside Where Clause but in my case, it is even in a subquery. I have made this query myself. Let me know if there is a better alternative for my query.
Looking for:
I am trying to get all those employees who are not busy between 14:00 & 15:00 where 14:00 and 15:00 is a time coming from input fields(like a search).
SELECT *
FROM `schedule`
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM `schedule`
WHERE ( IF(start_time < '14:00', '14:00', start_time) >= '14:00'
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00')
AND (IF(start_time < '14:00', '14:00', start_time) <= '15:00'
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00')
AND `appoint_date` = '2018-11-30')
mysql sql
1
I don't see how this query finds employees. You need something like SELECT FROM employees WHERE NOT EXISTS (a schedule at which that employee is busy during 2 and 3PM)
– Salman A
Nov 23 '18 at 8:38
@salman I am finding employees who are not having any appointment in the time range user searched.
– Sayed Mohd Ali
Nov 23 '18 at 8:42
It's just that you say you want employees, but you're returning schedules. But I assume that schedule table has something like an employee_id. So you could join it to your table with the employees. And probably group on the employee_id (or whatever it's called).
– LukStorms
Nov 23 '18 at 8:50
yes, schedule table has employee_id and I am also using join with employee table to find employee data. but this part of the query is just to get the employee id of those employees who do not have any appointment in the searched time. and also I am doing UNION of my query with another query which is simply find the employees id of the employee who do not exist in the appointment table that means they are also not having any appointment.
– Sayed Mohd Ali
Nov 23 '18 at 9:00
Btw, is a schedule with a range between '13:00' and '16:00' also considered as busy between '14:00' and '15:00'?
– LukStorms
Nov 23 '18 at 9:01
|
show 1 more comment
Working Query:
My query is working and I am also getting the result I desired. I just want to know if I am doing anything wrong because I heard it is not the right way to use IF inside Where Clause but in my case, it is even in a subquery. I have made this query myself. Let me know if there is a better alternative for my query.
Looking for:
I am trying to get all those employees who are not busy between 14:00 & 15:00 where 14:00 and 15:00 is a time coming from input fields(like a search).
SELECT *
FROM `schedule`
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM `schedule`
WHERE ( IF(start_time < '14:00', '14:00', start_time) >= '14:00'
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00')
AND (IF(start_time < '14:00', '14:00', start_time) <= '15:00'
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00')
AND `appoint_date` = '2018-11-30')
mysql sql
Working Query:
My query is working and I am also getting the result I desired. I just want to know if I am doing anything wrong because I heard it is not the right way to use IF inside Where Clause but in my case, it is even in a subquery. I have made this query myself. Let me know if there is a better alternative for my query.
Looking for:
I am trying to get all those employees who are not busy between 14:00 & 15:00 where 14:00 and 15:00 is a time coming from input fields(like a search).
SELECT *
FROM `schedule`
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM `schedule`
WHERE ( IF(start_time < '14:00', '14:00', start_time) >= '14:00'
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00')
AND (IF(start_time < '14:00', '14:00', start_time) <= '15:00'
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00')
AND `appoint_date` = '2018-11-30')
mysql sql
mysql sql
edited Nov 23 '18 at 8:12
Sayed Mohd Ali
asked Nov 23 '18 at 8:07
Sayed Mohd AliSayed Mohd Ali
1,5302520
1,5302520
1
I don't see how this query finds employees. You need something like SELECT FROM employees WHERE NOT EXISTS (a schedule at which that employee is busy during 2 and 3PM)
– Salman A
Nov 23 '18 at 8:38
@salman I am finding employees who are not having any appointment in the time range user searched.
– Sayed Mohd Ali
Nov 23 '18 at 8:42
It's just that you say you want employees, but you're returning schedules. But I assume that schedule table has something like an employee_id. So you could join it to your table with the employees. And probably group on the employee_id (or whatever it's called).
– LukStorms
Nov 23 '18 at 8:50
yes, schedule table has employee_id and I am also using join with employee table to find employee data. but this part of the query is just to get the employee id of those employees who do not have any appointment in the searched time. and also I am doing UNION of my query with another query which is simply find the employees id of the employee who do not exist in the appointment table that means they are also not having any appointment.
– Sayed Mohd Ali
Nov 23 '18 at 9:00
Btw, is a schedule with a range between '13:00' and '16:00' also considered as busy between '14:00' and '15:00'?
– LukStorms
Nov 23 '18 at 9:01
|
show 1 more comment
1
I don't see how this query finds employees. You need something like SELECT FROM employees WHERE NOT EXISTS (a schedule at which that employee is busy during 2 and 3PM)
– Salman A
Nov 23 '18 at 8:38
@salman I am finding employees who are not having any appointment in the time range user searched.
– Sayed Mohd Ali
Nov 23 '18 at 8:42
It's just that you say you want employees, but you're returning schedules. But I assume that schedule table has something like an employee_id. So you could join it to your table with the employees. And probably group on the employee_id (or whatever it's called).
– LukStorms
Nov 23 '18 at 8:50
yes, schedule table has employee_id and I am also using join with employee table to find employee data. but this part of the query is just to get the employee id of those employees who do not have any appointment in the searched time. and also I am doing UNION of my query with another query which is simply find the employees id of the employee who do not exist in the appointment table that means they are also not having any appointment.
– Sayed Mohd Ali
Nov 23 '18 at 9:00
Btw, is a schedule with a range between '13:00' and '16:00' also considered as busy between '14:00' and '15:00'?
– LukStorms
Nov 23 '18 at 9:01
1
1
I don't see how this query finds employees. You need something like SELECT FROM employees WHERE NOT EXISTS (a schedule at which that employee is busy during 2 and 3PM)
– Salman A
Nov 23 '18 at 8:38
I don't see how this query finds employees. You need something like SELECT FROM employees WHERE NOT EXISTS (a schedule at which that employee is busy during 2 and 3PM)
– Salman A
Nov 23 '18 at 8:38
@salman I am finding employees who are not having any appointment in the time range user searched.
– Sayed Mohd Ali
Nov 23 '18 at 8:42
@salman I am finding employees who are not having any appointment in the time range user searched.
– Sayed Mohd Ali
Nov 23 '18 at 8:42
It's just that you say you want employees, but you're returning schedules. But I assume that schedule table has something like an employee_id. So you could join it to your table with the employees. And probably group on the employee_id (or whatever it's called).
– LukStorms
Nov 23 '18 at 8:50
It's just that you say you want employees, but you're returning schedules. But I assume that schedule table has something like an employee_id. So you could join it to your table with the employees. And probably group on the employee_id (or whatever it's called).
– LukStorms
Nov 23 '18 at 8:50
yes, schedule table has employee_id and I am also using join with employee table to find employee data. but this part of the query is just to get the employee id of those employees who do not have any appointment in the searched time. and also I am doing UNION of my query with another query which is simply find the employees id of the employee who do not exist in the appointment table that means they are also not having any appointment.
– Sayed Mohd Ali
Nov 23 '18 at 9:00
yes, schedule table has employee_id and I am also using join with employee table to find employee data. but this part of the query is just to get the employee id of those employees who do not have any appointment in the searched time. and also I am doing UNION of my query with another query which is simply find the employees id of the employee who do not exist in the appointment table that means they are also not having any appointment.
– Sayed Mohd Ali
Nov 23 '18 at 9:00
Btw, is a schedule with a range between '13:00' and '16:00' also considered as busy between '14:00' and '15:00'?
– LukStorms
Nov 23 '18 at 9:01
Btw, is a schedule with a range between '13:00' and '16:00' also considered as busy between '14:00' and '15:00'?
– LukStorms
Nov 23 '18 at 9:01
|
show 1 more comment
5 Answers
5
active
oldest
votes
I don't even see the point of the IF
calls, and we may rewrite your query without them:
SELECT *
FROM schedule
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM schedule
WHERE
end_time >= '14:00' AND -- this
start_time <= '15:00' AND -- and this tests for all possible cases of overlap
appoint_date = '2018-11-30');
I was able to remove two of the conditions in your WHERE
clause because they would always be true. Here is one of the two examples:
IF (start_time < '14:00', '14:00', start_time) >= '14:00'
This will always be true, because any time which is 14:00
or earlier gets bumped up to 14:00
. So, such times would always be >= 14:00
. Similarly, any time already greater than 14:00
would also pass the check. So, this entire term can be removed, as well as one other term.
@Salman Thanks for the edit. I hope to also leave little green bundles of joy in your inbox at some point.
– Tim Biegeleisen
Nov 23 '18 at 8:34
IF is important without it I will not get the desired result the if is used because there may be some employees who will be busy a whole day and user search for 14:00 and 15:00, in that case, he will also get those employees who are busy a whole day. I don't want any employees who is busy.
– Sayed Mohd Ali
Nov 23 '18 at 8:38
@Sayed nah. it is bullet proof.
– Salman A
Nov 23 '18 at 8:39
@SalmanA what do you mean by bullet proof?
– Sayed Mohd Ali
Nov 23 '18 at 8:48
2
@SayedMohdAli This answer features the standard way to check for schedule clashes.. check the operators, it basically says does an appointment end AFTER the start time AND start BEFORE the end time? This gives the same logic as your IF magic
– Arth
Nov 23 '18 at 9:51
|
show 6 more comments
If the query is giving the desired results and is fast enough then it's fine.
You could make improvements, like creating indexes if they do not exist (I believe appointment_id
is indexed).
There is a chance that NOT EXISTS
instead of NOT IN
could be an improvement.
I would write the WHERE
part like this:
WHERE (IF(start_time < '14:00', '14:00', start_time) BETWEEN '14:00' AND '15:00')
AND (IF(end_time > '15:00', '15:00', end_time) BETWEEN '14:00' AND '15:00')
AND (`appoint_date` = '2018-11-30')
NOT EXISTS is faster than NOT IN?
– Sayed Mohd Ali
Nov 23 '18 at 8:51
1
@SayedMohdAli I've seen this claim in various discussions, but I have never experienced any difference, maybe because I don't have very large amount of data. If the query is fast then don't change it, the code is much more clearer withNOT IN
.
– forpas
Nov 23 '18 at 8:54
appointment_id is a primary key and what do you mean by indexed?
– Sayed Mohd Ali
Nov 23 '18 at 9:18
If appointment_id is a primary key then it is indexed. See this for the indexes: tutorialspoint.com/sql/sql-indexes.htm
– forpas
Nov 23 '18 at 9:20
tim answer was right he made my logic simple without IF
– Sayed Mohd Ali
Nov 23 '18 at 10:15
add a comment |
I prefer not eixsts
select * from schedule t where not exists
(select 1 from schedule t1 where
t1.appointment_id=t.appointment_id and
start_time>='14:00' and end_time<='15:00' and appoint_date` = '2018-11-30'
from )
Copy of my answer.
– Tim Biegeleisen
Nov 23 '18 at 8:28
@TimBiegeleisen you used exists? really
– Zaynul Abadin Tuhin
Nov 23 '18 at 8:29
How exactly does it work? It is wrong by the way. Fails for many cases.
– Salman A
Nov 23 '18 at 8:30
add a comment |
That IF can be usefull to default to a fixed time in the SELECT.
But as a criteria, using it to set a default is just overhead.
If you also don't want to include those that start before 14:00 and end after 15:00?
Then try this:
SELECT DISTINCT employee_id
FROM `schedule` s
WHERE `appoint_date` = '2018-11-30'
AND NOT EXISTS (
SELECT 1
FROM `schedule` s2
WHERE s2.`appoint_date` = '2018-11-30'
AND s2.start_time < '15:00'
AND s2.end_time > '14:00'
AND s2.appointment_id = s.appointment_id
);
You don't need five terms in theWHERE
clause. Read the question again.
– Tim Biegeleisen
Nov 23 '18 at 8:25
add a comment |
This is meant as a supplementary answer to Tim's solution
Breaking down your WHERE section (I have removed the surplus brackets)
WHERE IF(start_time < '14:00', '14:00', start_time) >= '14:00' /** Line 1 */
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00' /** Line 2 */
AND IF(start_time < '14:00', '14:00', start_time) <= '15:00' /** Line 3 */
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00' /** Line 4 */
AND `appoint_date` = '2018-11-30'
Looking at line 1, IF(start_time < '14:00', '14:00', start_time)
will always return a time greater than or equal to '14:00'
for a non-null start_time.. so this line is the same as WHERE start_time IS NOT NULL
Similarly line 4 can be rewritten AND end_time IS NOT NULL
Looking at line 2, it is fairly simple to see that this is equivalent to AND start_time <= '15:00'
. Any manipulation of start_time by the IF only affects times that would produce a true result, and keeps them true
Similarly line 3 can be rewritten AND end_time >= '14:00'
Putting this all together
WHERE start_time IS NOT NULL /** Line 1 */
AND end_time >= '14:00' /** Line 2 */
AND start_time <= '15:00' /** Line 3 */
AND end_time IS NOT NULL /** Line 4 */
AND `appoint_date` = '2018-11-30'
Now, as any comparison involving a null operand returns false, line 3 effectively gives you line 1 for free
Similarly, line 2 effectively gives you line 4 for free
Removing these superfluous lines, you end up with Tim's WHERE
WHERE end_time >= '14:00'
AND start_time <= '15:00'
AND appoint_date = '2018-11-30'
Addendum
A further benefit of refactoring away your IF clauses in Tim's WHERE is that this allows the engine to utilise an index on start_time, or end_time, to satisfy these conditions. This can give a significant performance benefit
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53442775%2fi-am-using-not-in-and-also-if-in-where-clause-of-subquery-mysql-is-it-right-way%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
I don't even see the point of the IF
calls, and we may rewrite your query without them:
SELECT *
FROM schedule
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM schedule
WHERE
end_time >= '14:00' AND -- this
start_time <= '15:00' AND -- and this tests for all possible cases of overlap
appoint_date = '2018-11-30');
I was able to remove two of the conditions in your WHERE
clause because they would always be true. Here is one of the two examples:
IF (start_time < '14:00', '14:00', start_time) >= '14:00'
This will always be true, because any time which is 14:00
or earlier gets bumped up to 14:00
. So, such times would always be >= 14:00
. Similarly, any time already greater than 14:00
would also pass the check. So, this entire term can be removed, as well as one other term.
@Salman Thanks for the edit. I hope to also leave little green bundles of joy in your inbox at some point.
– Tim Biegeleisen
Nov 23 '18 at 8:34
IF is important without it I will not get the desired result the if is used because there may be some employees who will be busy a whole day and user search for 14:00 and 15:00, in that case, he will also get those employees who are busy a whole day. I don't want any employees who is busy.
– Sayed Mohd Ali
Nov 23 '18 at 8:38
@Sayed nah. it is bullet proof.
– Salman A
Nov 23 '18 at 8:39
@SalmanA what do you mean by bullet proof?
– Sayed Mohd Ali
Nov 23 '18 at 8:48
2
@SayedMohdAli This answer features the standard way to check for schedule clashes.. check the operators, it basically says does an appointment end AFTER the start time AND start BEFORE the end time? This gives the same logic as your IF magic
– Arth
Nov 23 '18 at 9:51
|
show 6 more comments
I don't even see the point of the IF
calls, and we may rewrite your query without them:
SELECT *
FROM schedule
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM schedule
WHERE
end_time >= '14:00' AND -- this
start_time <= '15:00' AND -- and this tests for all possible cases of overlap
appoint_date = '2018-11-30');
I was able to remove two of the conditions in your WHERE
clause because they would always be true. Here is one of the two examples:
IF (start_time < '14:00', '14:00', start_time) >= '14:00'
This will always be true, because any time which is 14:00
or earlier gets bumped up to 14:00
. So, such times would always be >= 14:00
. Similarly, any time already greater than 14:00
would also pass the check. So, this entire term can be removed, as well as one other term.
@Salman Thanks for the edit. I hope to also leave little green bundles of joy in your inbox at some point.
– Tim Biegeleisen
Nov 23 '18 at 8:34
IF is important without it I will not get the desired result the if is used because there may be some employees who will be busy a whole day and user search for 14:00 and 15:00, in that case, he will also get those employees who are busy a whole day. I don't want any employees who is busy.
– Sayed Mohd Ali
Nov 23 '18 at 8:38
@Sayed nah. it is bullet proof.
– Salman A
Nov 23 '18 at 8:39
@SalmanA what do you mean by bullet proof?
– Sayed Mohd Ali
Nov 23 '18 at 8:48
2
@SayedMohdAli This answer features the standard way to check for schedule clashes.. check the operators, it basically says does an appointment end AFTER the start time AND start BEFORE the end time? This gives the same logic as your IF magic
– Arth
Nov 23 '18 at 9:51
|
show 6 more comments
I don't even see the point of the IF
calls, and we may rewrite your query without them:
SELECT *
FROM schedule
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM schedule
WHERE
end_time >= '14:00' AND -- this
start_time <= '15:00' AND -- and this tests for all possible cases of overlap
appoint_date = '2018-11-30');
I was able to remove two of the conditions in your WHERE
clause because they would always be true. Here is one of the two examples:
IF (start_time < '14:00', '14:00', start_time) >= '14:00'
This will always be true, because any time which is 14:00
or earlier gets bumped up to 14:00
. So, such times would always be >= 14:00
. Similarly, any time already greater than 14:00
would also pass the check. So, this entire term can be removed, as well as one other term.
I don't even see the point of the IF
calls, and we may rewrite your query without them:
SELECT *
FROM schedule
WHERE appointment_id NOT IN (
SELECT appointment_id
FROM schedule
WHERE
end_time >= '14:00' AND -- this
start_time <= '15:00' AND -- and this tests for all possible cases of overlap
appoint_date = '2018-11-30');
I was able to remove two of the conditions in your WHERE
clause because they would always be true. Here is one of the two examples:
IF (start_time < '14:00', '14:00', start_time) >= '14:00'
This will always be true, because any time which is 14:00
or earlier gets bumped up to 14:00
. So, such times would always be >= 14:00
. Similarly, any time already greater than 14:00
would also pass the check. So, this entire term can be removed, as well as one other term.
edited Nov 23 '18 at 10:17
answered Nov 23 '18 at 8:23
Tim BiegeleisenTim Biegeleisen
235k13100158
235k13100158
@Salman Thanks for the edit. I hope to also leave little green bundles of joy in your inbox at some point.
– Tim Biegeleisen
Nov 23 '18 at 8:34
IF is important without it I will not get the desired result the if is used because there may be some employees who will be busy a whole day and user search for 14:00 and 15:00, in that case, he will also get those employees who are busy a whole day. I don't want any employees who is busy.
– Sayed Mohd Ali
Nov 23 '18 at 8:38
@Sayed nah. it is bullet proof.
– Salman A
Nov 23 '18 at 8:39
@SalmanA what do you mean by bullet proof?
– Sayed Mohd Ali
Nov 23 '18 at 8:48
2
@SayedMohdAli This answer features the standard way to check for schedule clashes.. check the operators, it basically says does an appointment end AFTER the start time AND start BEFORE the end time? This gives the same logic as your IF magic
– Arth
Nov 23 '18 at 9:51
|
show 6 more comments
@Salman Thanks for the edit. I hope to also leave little green bundles of joy in your inbox at some point.
– Tim Biegeleisen
Nov 23 '18 at 8:34
IF is important without it I will not get the desired result the if is used because there may be some employees who will be busy a whole day and user search for 14:00 and 15:00, in that case, he will also get those employees who are busy a whole day. I don't want any employees who is busy.
– Sayed Mohd Ali
Nov 23 '18 at 8:38
@Sayed nah. it is bullet proof.
– Salman A
Nov 23 '18 at 8:39
@SalmanA what do you mean by bullet proof?
– Sayed Mohd Ali
Nov 23 '18 at 8:48
2
@SayedMohdAli This answer features the standard way to check for schedule clashes.. check the operators, it basically says does an appointment end AFTER the start time AND start BEFORE the end time? This gives the same logic as your IF magic
– Arth
Nov 23 '18 at 9:51
@Salman Thanks for the edit. I hope to also leave little green bundles of joy in your inbox at some point.
– Tim Biegeleisen
Nov 23 '18 at 8:34
@Salman Thanks for the edit. I hope to also leave little green bundles of joy in your inbox at some point.
– Tim Biegeleisen
Nov 23 '18 at 8:34
IF is important without it I will not get the desired result the if is used because there may be some employees who will be busy a whole day and user search for 14:00 and 15:00, in that case, he will also get those employees who are busy a whole day. I don't want any employees who is busy.
– Sayed Mohd Ali
Nov 23 '18 at 8:38
IF is important without it I will not get the desired result the if is used because there may be some employees who will be busy a whole day and user search for 14:00 and 15:00, in that case, he will also get those employees who are busy a whole day. I don't want any employees who is busy.
– Sayed Mohd Ali
Nov 23 '18 at 8:38
@Sayed nah. it is bullet proof.
– Salman A
Nov 23 '18 at 8:39
@Sayed nah. it is bullet proof.
– Salman A
Nov 23 '18 at 8:39
@SalmanA what do you mean by bullet proof?
– Sayed Mohd Ali
Nov 23 '18 at 8:48
@SalmanA what do you mean by bullet proof?
– Sayed Mohd Ali
Nov 23 '18 at 8:48
2
2
@SayedMohdAli This answer features the standard way to check for schedule clashes.. check the operators, it basically says does an appointment end AFTER the start time AND start BEFORE the end time? This gives the same logic as your IF magic
– Arth
Nov 23 '18 at 9:51
@SayedMohdAli This answer features the standard way to check for schedule clashes.. check the operators, it basically says does an appointment end AFTER the start time AND start BEFORE the end time? This gives the same logic as your IF magic
– Arth
Nov 23 '18 at 9:51
|
show 6 more comments
If the query is giving the desired results and is fast enough then it's fine.
You could make improvements, like creating indexes if they do not exist (I believe appointment_id
is indexed).
There is a chance that NOT EXISTS
instead of NOT IN
could be an improvement.
I would write the WHERE
part like this:
WHERE (IF(start_time < '14:00', '14:00', start_time) BETWEEN '14:00' AND '15:00')
AND (IF(end_time > '15:00', '15:00', end_time) BETWEEN '14:00' AND '15:00')
AND (`appoint_date` = '2018-11-30')
NOT EXISTS is faster than NOT IN?
– Sayed Mohd Ali
Nov 23 '18 at 8:51
1
@SayedMohdAli I've seen this claim in various discussions, but I have never experienced any difference, maybe because I don't have very large amount of data. If the query is fast then don't change it, the code is much more clearer withNOT IN
.
– forpas
Nov 23 '18 at 8:54
appointment_id is a primary key and what do you mean by indexed?
– Sayed Mohd Ali
Nov 23 '18 at 9:18
If appointment_id is a primary key then it is indexed. See this for the indexes: tutorialspoint.com/sql/sql-indexes.htm
– forpas
Nov 23 '18 at 9:20
tim answer was right he made my logic simple without IF
– Sayed Mohd Ali
Nov 23 '18 at 10:15
add a comment |
If the query is giving the desired results and is fast enough then it's fine.
You could make improvements, like creating indexes if they do not exist (I believe appointment_id
is indexed).
There is a chance that NOT EXISTS
instead of NOT IN
could be an improvement.
I would write the WHERE
part like this:
WHERE (IF(start_time < '14:00', '14:00', start_time) BETWEEN '14:00' AND '15:00')
AND (IF(end_time > '15:00', '15:00', end_time) BETWEEN '14:00' AND '15:00')
AND (`appoint_date` = '2018-11-30')
NOT EXISTS is faster than NOT IN?
– Sayed Mohd Ali
Nov 23 '18 at 8:51
1
@SayedMohdAli I've seen this claim in various discussions, but I have never experienced any difference, maybe because I don't have very large amount of data. If the query is fast then don't change it, the code is much more clearer withNOT IN
.
– forpas
Nov 23 '18 at 8:54
appointment_id is a primary key and what do you mean by indexed?
– Sayed Mohd Ali
Nov 23 '18 at 9:18
If appointment_id is a primary key then it is indexed. See this for the indexes: tutorialspoint.com/sql/sql-indexes.htm
– forpas
Nov 23 '18 at 9:20
tim answer was right he made my logic simple without IF
– Sayed Mohd Ali
Nov 23 '18 at 10:15
add a comment |
If the query is giving the desired results and is fast enough then it's fine.
You could make improvements, like creating indexes if they do not exist (I believe appointment_id
is indexed).
There is a chance that NOT EXISTS
instead of NOT IN
could be an improvement.
I would write the WHERE
part like this:
WHERE (IF(start_time < '14:00', '14:00', start_time) BETWEEN '14:00' AND '15:00')
AND (IF(end_time > '15:00', '15:00', end_time) BETWEEN '14:00' AND '15:00')
AND (`appoint_date` = '2018-11-30')
If the query is giving the desired results and is fast enough then it's fine.
You could make improvements, like creating indexes if they do not exist (I believe appointment_id
is indexed).
There is a chance that NOT EXISTS
instead of NOT IN
could be an improvement.
I would write the WHERE
part like this:
WHERE (IF(start_time < '14:00', '14:00', start_time) BETWEEN '14:00' AND '15:00')
AND (IF(end_time > '15:00', '15:00', end_time) BETWEEN '14:00' AND '15:00')
AND (`appoint_date` = '2018-11-30')
answered Nov 23 '18 at 8:29
forpasforpas
18.5k3728
18.5k3728
NOT EXISTS is faster than NOT IN?
– Sayed Mohd Ali
Nov 23 '18 at 8:51
1
@SayedMohdAli I've seen this claim in various discussions, but I have never experienced any difference, maybe because I don't have very large amount of data. If the query is fast then don't change it, the code is much more clearer withNOT IN
.
– forpas
Nov 23 '18 at 8:54
appointment_id is a primary key and what do you mean by indexed?
– Sayed Mohd Ali
Nov 23 '18 at 9:18
If appointment_id is a primary key then it is indexed. See this for the indexes: tutorialspoint.com/sql/sql-indexes.htm
– forpas
Nov 23 '18 at 9:20
tim answer was right he made my logic simple without IF
– Sayed Mohd Ali
Nov 23 '18 at 10:15
add a comment |
NOT EXISTS is faster than NOT IN?
– Sayed Mohd Ali
Nov 23 '18 at 8:51
1
@SayedMohdAli I've seen this claim in various discussions, but I have never experienced any difference, maybe because I don't have very large amount of data. If the query is fast then don't change it, the code is much more clearer withNOT IN
.
– forpas
Nov 23 '18 at 8:54
appointment_id is a primary key and what do you mean by indexed?
– Sayed Mohd Ali
Nov 23 '18 at 9:18
If appointment_id is a primary key then it is indexed. See this for the indexes: tutorialspoint.com/sql/sql-indexes.htm
– forpas
Nov 23 '18 at 9:20
tim answer was right he made my logic simple without IF
– Sayed Mohd Ali
Nov 23 '18 at 10:15
NOT EXISTS is faster than NOT IN?
– Sayed Mohd Ali
Nov 23 '18 at 8:51
NOT EXISTS is faster than NOT IN?
– Sayed Mohd Ali
Nov 23 '18 at 8:51
1
1
@SayedMohdAli I've seen this claim in various discussions, but I have never experienced any difference, maybe because I don't have very large amount of data. If the query is fast then don't change it, the code is much more clearer with
NOT IN
.– forpas
Nov 23 '18 at 8:54
@SayedMohdAli I've seen this claim in various discussions, but I have never experienced any difference, maybe because I don't have very large amount of data. If the query is fast then don't change it, the code is much more clearer with
NOT IN
.– forpas
Nov 23 '18 at 8:54
appointment_id is a primary key and what do you mean by indexed?
– Sayed Mohd Ali
Nov 23 '18 at 9:18
appointment_id is a primary key and what do you mean by indexed?
– Sayed Mohd Ali
Nov 23 '18 at 9:18
If appointment_id is a primary key then it is indexed. See this for the indexes: tutorialspoint.com/sql/sql-indexes.htm
– forpas
Nov 23 '18 at 9:20
If appointment_id is a primary key then it is indexed. See this for the indexes: tutorialspoint.com/sql/sql-indexes.htm
– forpas
Nov 23 '18 at 9:20
tim answer was right he made my logic simple without IF
– Sayed Mohd Ali
Nov 23 '18 at 10:15
tim answer was right he made my logic simple without IF
– Sayed Mohd Ali
Nov 23 '18 at 10:15
add a comment |
I prefer not eixsts
select * from schedule t where not exists
(select 1 from schedule t1 where
t1.appointment_id=t.appointment_id and
start_time>='14:00' and end_time<='15:00' and appoint_date` = '2018-11-30'
from )
Copy of my answer.
– Tim Biegeleisen
Nov 23 '18 at 8:28
@TimBiegeleisen you used exists? really
– Zaynul Abadin Tuhin
Nov 23 '18 at 8:29
How exactly does it work? It is wrong by the way. Fails for many cases.
– Salman A
Nov 23 '18 at 8:30
add a comment |
I prefer not eixsts
select * from schedule t where not exists
(select 1 from schedule t1 where
t1.appointment_id=t.appointment_id and
start_time>='14:00' and end_time<='15:00' and appoint_date` = '2018-11-30'
from )
Copy of my answer.
– Tim Biegeleisen
Nov 23 '18 at 8:28
@TimBiegeleisen you used exists? really
– Zaynul Abadin Tuhin
Nov 23 '18 at 8:29
How exactly does it work? It is wrong by the way. Fails for many cases.
– Salman A
Nov 23 '18 at 8:30
add a comment |
I prefer not eixsts
select * from schedule t where not exists
(select 1 from schedule t1 where
t1.appointment_id=t.appointment_id and
start_time>='14:00' and end_time<='15:00' and appoint_date` = '2018-11-30'
from )
I prefer not eixsts
select * from schedule t where not exists
(select 1 from schedule t1 where
t1.appointment_id=t.appointment_id and
start_time>='14:00' and end_time<='15:00' and appoint_date` = '2018-11-30'
from )
edited Nov 23 '18 at 8:40
answered Nov 23 '18 at 8:26
Zaynul Abadin TuhinZaynul Abadin Tuhin
18.2k21134
18.2k21134
Copy of my answer.
– Tim Biegeleisen
Nov 23 '18 at 8:28
@TimBiegeleisen you used exists? really
– Zaynul Abadin Tuhin
Nov 23 '18 at 8:29
How exactly does it work? It is wrong by the way. Fails for many cases.
– Salman A
Nov 23 '18 at 8:30
add a comment |
Copy of my answer.
– Tim Biegeleisen
Nov 23 '18 at 8:28
@TimBiegeleisen you used exists? really
– Zaynul Abadin Tuhin
Nov 23 '18 at 8:29
How exactly does it work? It is wrong by the way. Fails for many cases.
– Salman A
Nov 23 '18 at 8:30
Copy of my answer.
– Tim Biegeleisen
Nov 23 '18 at 8:28
Copy of my answer.
– Tim Biegeleisen
Nov 23 '18 at 8:28
@TimBiegeleisen you used exists? really
– Zaynul Abadin Tuhin
Nov 23 '18 at 8:29
@TimBiegeleisen you used exists? really
– Zaynul Abadin Tuhin
Nov 23 '18 at 8:29
How exactly does it work? It is wrong by the way. Fails for many cases.
– Salman A
Nov 23 '18 at 8:30
How exactly does it work? It is wrong by the way. Fails for many cases.
– Salman A
Nov 23 '18 at 8:30
add a comment |
That IF can be usefull to default to a fixed time in the SELECT.
But as a criteria, using it to set a default is just overhead.
If you also don't want to include those that start before 14:00 and end after 15:00?
Then try this:
SELECT DISTINCT employee_id
FROM `schedule` s
WHERE `appoint_date` = '2018-11-30'
AND NOT EXISTS (
SELECT 1
FROM `schedule` s2
WHERE s2.`appoint_date` = '2018-11-30'
AND s2.start_time < '15:00'
AND s2.end_time > '14:00'
AND s2.appointment_id = s.appointment_id
);
You don't need five terms in theWHERE
clause. Read the question again.
– Tim Biegeleisen
Nov 23 '18 at 8:25
add a comment |
That IF can be usefull to default to a fixed time in the SELECT.
But as a criteria, using it to set a default is just overhead.
If you also don't want to include those that start before 14:00 and end after 15:00?
Then try this:
SELECT DISTINCT employee_id
FROM `schedule` s
WHERE `appoint_date` = '2018-11-30'
AND NOT EXISTS (
SELECT 1
FROM `schedule` s2
WHERE s2.`appoint_date` = '2018-11-30'
AND s2.start_time < '15:00'
AND s2.end_time > '14:00'
AND s2.appointment_id = s.appointment_id
);
You don't need five terms in theWHERE
clause. Read the question again.
– Tim Biegeleisen
Nov 23 '18 at 8:25
add a comment |
That IF can be usefull to default to a fixed time in the SELECT.
But as a criteria, using it to set a default is just overhead.
If you also don't want to include those that start before 14:00 and end after 15:00?
Then try this:
SELECT DISTINCT employee_id
FROM `schedule` s
WHERE `appoint_date` = '2018-11-30'
AND NOT EXISTS (
SELECT 1
FROM `schedule` s2
WHERE s2.`appoint_date` = '2018-11-30'
AND s2.start_time < '15:00'
AND s2.end_time > '14:00'
AND s2.appointment_id = s.appointment_id
);
That IF can be usefull to default to a fixed time in the SELECT.
But as a criteria, using it to set a default is just overhead.
If you also don't want to include those that start before 14:00 and end after 15:00?
Then try this:
SELECT DISTINCT employee_id
FROM `schedule` s
WHERE `appoint_date` = '2018-11-30'
AND NOT EXISTS (
SELECT 1
FROM `schedule` s2
WHERE s2.`appoint_date` = '2018-11-30'
AND s2.start_time < '15:00'
AND s2.end_time > '14:00'
AND s2.appointment_id = s.appointment_id
);
edited Nov 23 '18 at 9:33
answered Nov 23 '18 at 8:25
LukStormsLukStorms
14.1k31734
14.1k31734
You don't need five terms in theWHERE
clause. Read the question again.
– Tim Biegeleisen
Nov 23 '18 at 8:25
add a comment |
You don't need five terms in theWHERE
clause. Read the question again.
– Tim Biegeleisen
Nov 23 '18 at 8:25
You don't need five terms in the
WHERE
clause. Read the question again.– Tim Biegeleisen
Nov 23 '18 at 8:25
You don't need five terms in the
WHERE
clause. Read the question again.– Tim Biegeleisen
Nov 23 '18 at 8:25
add a comment |
This is meant as a supplementary answer to Tim's solution
Breaking down your WHERE section (I have removed the surplus brackets)
WHERE IF(start_time < '14:00', '14:00', start_time) >= '14:00' /** Line 1 */
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00' /** Line 2 */
AND IF(start_time < '14:00', '14:00', start_time) <= '15:00' /** Line 3 */
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00' /** Line 4 */
AND `appoint_date` = '2018-11-30'
Looking at line 1, IF(start_time < '14:00', '14:00', start_time)
will always return a time greater than or equal to '14:00'
for a non-null start_time.. so this line is the same as WHERE start_time IS NOT NULL
Similarly line 4 can be rewritten AND end_time IS NOT NULL
Looking at line 2, it is fairly simple to see that this is equivalent to AND start_time <= '15:00'
. Any manipulation of start_time by the IF only affects times that would produce a true result, and keeps them true
Similarly line 3 can be rewritten AND end_time >= '14:00'
Putting this all together
WHERE start_time IS NOT NULL /** Line 1 */
AND end_time >= '14:00' /** Line 2 */
AND start_time <= '15:00' /** Line 3 */
AND end_time IS NOT NULL /** Line 4 */
AND `appoint_date` = '2018-11-30'
Now, as any comparison involving a null operand returns false, line 3 effectively gives you line 1 for free
Similarly, line 2 effectively gives you line 4 for free
Removing these superfluous lines, you end up with Tim's WHERE
WHERE end_time >= '14:00'
AND start_time <= '15:00'
AND appoint_date = '2018-11-30'
Addendum
A further benefit of refactoring away your IF clauses in Tim's WHERE is that this allows the engine to utilise an index on start_time, or end_time, to satisfy these conditions. This can give a significant performance benefit
add a comment |
This is meant as a supplementary answer to Tim's solution
Breaking down your WHERE section (I have removed the surplus brackets)
WHERE IF(start_time < '14:00', '14:00', start_time) >= '14:00' /** Line 1 */
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00' /** Line 2 */
AND IF(start_time < '14:00', '14:00', start_time) <= '15:00' /** Line 3 */
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00' /** Line 4 */
AND `appoint_date` = '2018-11-30'
Looking at line 1, IF(start_time < '14:00', '14:00', start_time)
will always return a time greater than or equal to '14:00'
for a non-null start_time.. so this line is the same as WHERE start_time IS NOT NULL
Similarly line 4 can be rewritten AND end_time IS NOT NULL
Looking at line 2, it is fairly simple to see that this is equivalent to AND start_time <= '15:00'
. Any manipulation of start_time by the IF only affects times that would produce a true result, and keeps them true
Similarly line 3 can be rewritten AND end_time >= '14:00'
Putting this all together
WHERE start_time IS NOT NULL /** Line 1 */
AND end_time >= '14:00' /** Line 2 */
AND start_time <= '15:00' /** Line 3 */
AND end_time IS NOT NULL /** Line 4 */
AND `appoint_date` = '2018-11-30'
Now, as any comparison involving a null operand returns false, line 3 effectively gives you line 1 for free
Similarly, line 2 effectively gives you line 4 for free
Removing these superfluous lines, you end up with Tim's WHERE
WHERE end_time >= '14:00'
AND start_time <= '15:00'
AND appoint_date = '2018-11-30'
Addendum
A further benefit of refactoring away your IF clauses in Tim's WHERE is that this allows the engine to utilise an index on start_time, or end_time, to satisfy these conditions. This can give a significant performance benefit
add a comment |
This is meant as a supplementary answer to Tim's solution
Breaking down your WHERE section (I have removed the surplus brackets)
WHERE IF(start_time < '14:00', '14:00', start_time) >= '14:00' /** Line 1 */
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00' /** Line 2 */
AND IF(start_time < '14:00', '14:00', start_time) <= '15:00' /** Line 3 */
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00' /** Line 4 */
AND `appoint_date` = '2018-11-30'
Looking at line 1, IF(start_time < '14:00', '14:00', start_time)
will always return a time greater than or equal to '14:00'
for a non-null start_time.. so this line is the same as WHERE start_time IS NOT NULL
Similarly line 4 can be rewritten AND end_time IS NOT NULL
Looking at line 2, it is fairly simple to see that this is equivalent to AND start_time <= '15:00'
. Any manipulation of start_time by the IF only affects times that would produce a true result, and keeps them true
Similarly line 3 can be rewritten AND end_time >= '14:00'
Putting this all together
WHERE start_time IS NOT NULL /** Line 1 */
AND end_time >= '14:00' /** Line 2 */
AND start_time <= '15:00' /** Line 3 */
AND end_time IS NOT NULL /** Line 4 */
AND `appoint_date` = '2018-11-30'
Now, as any comparison involving a null operand returns false, line 3 effectively gives you line 1 for free
Similarly, line 2 effectively gives you line 4 for free
Removing these superfluous lines, you end up with Tim's WHERE
WHERE end_time >= '14:00'
AND start_time <= '15:00'
AND appoint_date = '2018-11-30'
Addendum
A further benefit of refactoring away your IF clauses in Tim's WHERE is that this allows the engine to utilise an index on start_time, or end_time, to satisfy these conditions. This can give a significant performance benefit
This is meant as a supplementary answer to Tim's solution
Breaking down your WHERE section (I have removed the surplus brackets)
WHERE IF(start_time < '14:00', '14:00', start_time) >= '14:00' /** Line 1 */
AND IF(end_time > '15:00', '15:00', end_time) >= '14:00' /** Line 2 */
AND IF(start_time < '14:00', '14:00', start_time) <= '15:00' /** Line 3 */
AND IF(end_time > '15:00', '15:00', end_time) <= '15:00' /** Line 4 */
AND `appoint_date` = '2018-11-30'
Looking at line 1, IF(start_time < '14:00', '14:00', start_time)
will always return a time greater than or equal to '14:00'
for a non-null start_time.. so this line is the same as WHERE start_time IS NOT NULL
Similarly line 4 can be rewritten AND end_time IS NOT NULL
Looking at line 2, it is fairly simple to see that this is equivalent to AND start_time <= '15:00'
. Any manipulation of start_time by the IF only affects times that would produce a true result, and keeps them true
Similarly line 3 can be rewritten AND end_time >= '14:00'
Putting this all together
WHERE start_time IS NOT NULL /** Line 1 */
AND end_time >= '14:00' /** Line 2 */
AND start_time <= '15:00' /** Line 3 */
AND end_time IS NOT NULL /** Line 4 */
AND `appoint_date` = '2018-11-30'
Now, as any comparison involving a null operand returns false, line 3 effectively gives you line 1 for free
Similarly, line 2 effectively gives you line 4 for free
Removing these superfluous lines, you end up with Tim's WHERE
WHERE end_time >= '14:00'
AND start_time <= '15:00'
AND appoint_date = '2018-11-30'
Addendum
A further benefit of refactoring away your IF clauses in Tim's WHERE is that this allows the engine to utilise an index on start_time, or end_time, to satisfy these conditions. This can give a significant performance benefit
edited Nov 23 '18 at 10:30
answered Nov 23 '18 at 10:19
ArthArth
8,98342348
8,98342348
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53442775%2fi-am-using-not-in-and-also-if-in-where-clause-of-subquery-mysql-is-it-right-way%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
I don't see how this query finds employees. You need something like SELECT FROM employees WHERE NOT EXISTS (a schedule at which that employee is busy during 2 and 3PM)
– Salman A
Nov 23 '18 at 8:38
@salman I am finding employees who are not having any appointment in the time range user searched.
– Sayed Mohd Ali
Nov 23 '18 at 8:42
It's just that you say you want employees, but you're returning schedules. But I assume that schedule table has something like an employee_id. So you could join it to your table with the employees. And probably group on the employee_id (or whatever it's called).
– LukStorms
Nov 23 '18 at 8:50
yes, schedule table has employee_id and I am also using join with employee table to find employee data. but this part of the query is just to get the employee id of those employees who do not have any appointment in the searched time. and also I am doing UNION of my query with another query which is simply find the employees id of the employee who do not exist in the appointment table that means they are also not having any appointment.
– Sayed Mohd Ali
Nov 23 '18 at 9:00
Btw, is a schedule with a range between '13:00' and '16:00' also considered as busy between '14:00' and '15:00'?
– LukStorms
Nov 23 '18 at 9:01