Как упростить встроенный MySQL запрос в JOIN? - PullRequest
1 голос
/ 14 июля 2011

Я недавно прочитал кое-что о проблемах производительности со встроенными запросами 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 ]

5 голосов
/ 14 июля 2011

Вместо 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 голос
/ 14 июля 2011

Я бы использовал 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 в основном запросе.

0 голосов
/ 14 июля 2011

Вы можете попробовать это также:

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'
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...