我在子查询mysql的where子句中使用not-in和if是否正确?

wvt8vs2t  于 2021-06-17  发布在  Mysql
关注(0)|答案(5)|浏览(301)

工作查询:我的查询工作,我也得到了我想要的结果。我只想知道我是否做错了什么,因为我听说在where子句中使用if不是正确的方法,但在我的情况下,它甚至在子查询中。我自己提出了这个问题。让我知道是否有更好的替代我的查询。
寻找:我试图让所有的员工谁是14:00和15:00之间不忙,其中14:00和15:00是一个时间从输入字段来(如搜索)。

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')
bf1o4zei

bf1o4zei1#

我甚至不明白 IF 调用,我们可以重写您的查询,而不使用它们:

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');

我能解除你的两个条件 WHERE 因为它们永远都是真的。以下是两个示例之一:

IF (start_time < '14:00', '14:00', start_time) >= '14:00'

这永远是真的,因为任何时候 14:00 或者更早的时候 14:00 . 所以,这样的时刻总是 >= 14:00 . 类似地,任何时间已经大于 14:00 也能通过检查。所以,这个术语和另外一个术语都可以去掉。

kx1ctssn

kx1ctssn2#

如果查询给出了所需的结果并且足够快,那么就可以了。
你可以做一些改进,比如在索引不存在的情况下创建索引(我相信) appointment_id 索引)。
有可能 NOT EXISTS 而不是 NOT IN 可能是个进步。
我会写 WHERE 像这样的部分:

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')
piwo6bdm

piwo6bdm3#

我更喜欢 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 )

np8igboo

np8igboo4#

如果在select中默认为一个固定的时间,那么if是有用的。
但作为一个标准,使用它来设置默认值只是开销。
如果你也不想包括那些14:00之前开始,15:00之后结束的?
那么试试这个:

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
      );
vybvopom

vybvopom5#

这是tim解决方案的补充答案
分解where部分(我去掉了多余的括号)

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'

看一号线, IF(start_time < '14:00', '14:00', start_time) 将始终返回大于或等于的时间 '14:00' 对于非空的开始时间。。所以这条线和 WHERE start_time IS NOT NULL 同样,第4行也可以重写 AND end_time IS NOT NULL 看第2行,很容易看出这相当于 AND start_time <= '15:00' . if对开始时间的任何操作只会影响将产生真实结果的时间,并使其保持真实
同样,第3行也可以重写 AND end_time >= '14:00' 把这些放在一起

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'

现在,由于任何涉及空操作数的比较都返回false,第3行实际上免费提供第1行
同样,第2行实际上免费提供第4行
去掉这些多余的台词,你就会得到蒂姆在哪里

WHERE end_time >= '14:00' 
  AND start_time <= '15:00'
  AND appoint_date = '2018-11-30'

附录
在tim的where中重构if子句的另一个好处是,这允许引擎在开始时间或结束时间使用索引来满足这些条件。这可以提供显著的性能优势

相关问题