2011-07-14 5 views
1

私は最近、埋め込まれたmysqlクエリでパフォーマンスの問題について何かを読んでいましたので、私は次のものを "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 ; 

ロジックは、それらに関連記事を持っているすべてのカテゴリを選択するには、基本的には次のとおりです。

私は2つのテーブルを持っています。 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')"; 

は、私が「結合」することは依然として新たなんだ、とわかりませんミックスで "COUNT(*)"を使用するときにそれを変更する方法。

+0

Jay:上記のクエリを再解析し、実装しようとしているロジックを言葉で教えてください。 –

+0

@Mitch小麦お返事ありがとう!基本的には、関連する記事を持つすべてのカテゴリを選択することです。 'blog_articles'テーブルの各行には「category_name」が含まれています。 – Jay

+1

とwww.devshed.com/c/a/MySQL/Understanding-SQL-Joins/ JOINsの詳細については – Leslie

答えて

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

を参照してください。サブクエリの 'blog_categories'は冗長です(OPのクエリとあなたの両方)。そこには、関連する記事を持つカテゴリだけを選択するという考えがあるようです。しかし、実際のスクリプト(つまり、バージョンと@ Jayの両方)は、データベースに少なくとも1つの記事があるかどうかに応じて、すべてのカテゴリまたはなしを選択します。 –

+1

サブクエリは '(SELECT * FROM blog_articles WHERE blog_articles.category_name = blog_categories.category_name)'であるべきです。 –

+0

@Andriy M:私は急いでポスターの論理を調べなかった!私は更新します。ありがとう。 –

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' 
) 
+2

-1、 'IN(SELECT'は非常に遅いです。MySQLではこれを使用しないでください。代わりに' where exists'を使用してください。 – Johan

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とは関係ありません。

関連する問題