2016-07-03 115 views
0

请看看这两个查询:VS外部查询

一:

INSERT INTO QandA (id, body, type, related, author_id, date_time) 
    SELECT NULL, :body, 0, NULL, :id, unix_timestamp 
    FROM (select count(*) as num_month, 
       count(date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 day))) as num_day, 
       count(date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 90 minute))) as num_90min 
      from QANDA 
      where author_id = :id and 
       type = 0 and 
       date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 50 day)) 
     ) a 
    WHERE num_month < 50 and num_day < 6 and num_90min < 1; 

二:

INSERT INTO QandA (id, body, type, related, author_id, date_time) 
SELECT NULL, :body, 0, NULL, :id, unix_timestamp 
FROM dual 
WHERE user_id = :id 
    AND NOT EXISTS (
     SELECT count(*) AS num_month 
       count(date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 day))) as num_day, 
       count(date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 90 minute))) as num_90min 
     FROM QandA 
     WHERE author_id = :id and 
       type = 0 and 
       date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 50 day)) 
     HAVING num_90min > 50 
      OR num_day > 6 
      OR num_month > 1 
    ) 

正如你看到他们两个areidentical,只是第一个使用外部查询和第二个使用having条款。那么哪种方法更好?还是有第三种方法比他们更好?

回答

0

第一个是标准的SQL,所以你应该理解它。

第二个是MySQL中having子句的扩展。通常,having子句只能用于聚合查询 - 您会在查询中看到聚合函数。在MySQL(和其他几个数据库)中,having允许使用列别名,而WHERE子句不允许。

让我们添加一个更重要的考虑事项。一般来说,MySQL 实现了子查询。这意味着子查询会产生额外的开销来写出数据并将其读回。大多数其他数据库具有更好的优化器,并且不会实现FROM子句中的所有/大部分子查询。

因此,为了提高效率,MySQL允许您在非聚合查询中使用HAVING子句。在这种情况下,它的功能就像WHERE子句,除了可以引用列别名。

结论:第一个更好,因为它是更标准的SQL。第二个更好,因为它应该运行得更快。一切都取决于你的意思是“更好”。