如何将嵌入式mysql查询简化为JOIN?

时间:2011-07-14 05:15:21

标签: mysql sql performance join

我最近阅读了一些关于嵌入式mysql查询的性能问题的内容,所以我想知道如何将以下内容更改为“JOIN”(假设性能更好?)。

我有两张桌子:

CREATE TABLE IF NOT EXISTS `blog_categories` (
  `category_id` int(11) NOT NULL AUTO_INCREMENT,
  `category_name` varchar(300) COLLATE utf8_unicode_ci NOT NULL,
  `category_name_url` varchar(300) COLLATE utf8_unicode_ci NOT NULL,
  `category_status` enum('online','offline') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'offline'
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=8 ;


CREATE TABLE IF NOT EXISTS `blog_articles` (
  `article_id` int(11) NOT NULL AUTO_INCREMENT,
  `article_title` tinytext COLLATE utf8_unicode_ci NOT NULL,
  `category_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=26 ;

逻辑基本上是选择所有与其相关联的文章的类别。 blog_articles表中的每一行都包含category_name
这是我正在使用的查询(检查并正常工作):

$sql = "SELECT category_name
     , category_name_url 
   FROM blog_categories 
   WHERE (
     (SELECT COUNT(*) 
      FROM blog_articles, blog_categories 
      WHERE blog_articles.category_name = blog_categories.category_name
     ) > 0 
     AND blog_categories.category_status = 'online')";

我还是“JOIN”的新手,并且在混音中使用“COUNT(*)”时也不确定如何更改它。

3 个答案:

答案 0 :(得分:5)

而不是COUNT(*) > 0,请使用EXISTS

"SELECT category_name, category_name_url FROM blog_categories WHERE EXISTS (" . 
              "(SELECT 1 FROM blog_articles INNER JOIN blog_categories 
                ON blog_articles.category_name = blog_categories.category_name)  AND " . 
              "blog_categories.category_status = 'online'" . 
              ")";

这是旧式连接语法:

SELECT 1 FROM blog_articles, blog_categories 
WHERE blog_articles.category_name = blog_categories.category_name

这是同样的ANSI形式:

SELECT 1 
FROM blog_articles
INNER JOIN blog_categories 
    ON blog_articles.category_name = blog_categories.category_name

更新(响应海报评论):此查询可满足您的需求:

"SELECT category_name, category_name_url 
 FROM blog_categories 
 WHERE category_name IN (SELECT DISTINCT category_name FROM blog_articles)
 AND blog_categories.category_status = 'online'"

答案 1 :(得分:1)

我使用EXISTS

$sql = "SELECT category_name
             , category_name_url 
        FROM blog_categories 
        WHERE EXISTS
          ( SELECT * 
            FROM blog_articles 
            WHERE blog_articles.category_name = blog_categories.category_name
          ) 
        AND blog_categories.category_status = 'online'
       ";

JOIN

$sql = "SELECT c.category_name
             , c.category_name_url 
        FROM blog_categories AS c 
          JOIN blog_articles AS a
            ON a.category_name = c.category_name
        WHERE c.category_status = 'online'
        GROUP BY c.category_name
       ";

@Jay:我怀疑你的查询是否正确,只显示有文章发布的类别。它统计所有类别的所有文章,然后显示所有类别(如果计数> 0)或根本不显示任何类别(如果计数= 0)。

原因是子查询中的blog_categories与任何条件下的主查询中的blog_categories无关。

答案 2 :(得分:0)

你也可以试试这个:

SELECT category_name, category_name_url
FROM blog_categories
WHERE category_id IN (
    SELECT blog_categories.category_id
    FROM blog_articles
    INNER JOIN blog_categories
        ON blog_categories.category_name = blog_articles.category_name
        AND blog_categories.category_status = 'online'
)