有VS外部查询

时间:2016-07-03 14:53:08

标签: mysql sql

请看一下这两个问题:

一:

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 
    )

如您所见,两者都是相同的,只有第一个使用外部查询,第二个使用 having 子句。哪种方法更好?或者有没有比他们更好的第三种方法?

1 个答案:

答案 0 :(得分:0)

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

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

让我们再添加一个重要的考虑因素。通常,MySQL 实现子查询。这意味着子查询会产生额外的开销来写出数据并将其读回。大多数其他数据库都有更好的优化器,并且没有实现FROM子句中的所有/大多数子查询。

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

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