1

それはそれらの日のうちの1つでしたが、私はこれを理解することができません.

次のクエリがあります。

SELECT * FROM wp_posts
JOIN wp_term_relationships ON wp_term_relationships.object_id = wp_posts.ID
WHERE term_taxonomy_id = 80

明らかに、これはカテゴリ ID 80 にあるすべての投稿を選択します。私がする必要があるのは、カテゴリ 80 にあるがカテゴリ 109 にないすべての投稿を選択することです。

これを試してみましたが、カテゴリ 80 から同じ投稿を選択するだけです。

SELECT * FROM wp_posts
JOIN wp_term_relationships ON wp_term_relationships.object_id = wp_posts.ID
WHERE term_taxonomy_id = 80
AND term_taxonomy_id = 109

テーブル構造は次のとおりです。

wp_posts

|    ID    |
------------
|    1     |
|    2     |

wp_term_relationships

| object_id | term_taxonomy_id |
|-----------|------------------|
|     1     |       80         |
|     2     |       80         |
|     1     |       109        |

object_id は post_id に一致します

ID 1 は 80 と 109 の両方にあるため、クエリは ID 2 のみを返す必要があります。

私はこれを何百万回も行ってきたことを知っていますが、私の人生ではこれを機能させることはできません. 何か助けはありますか?

4

3 に答える 3

2

あなたは書ける:

SELECT *
  FROM wp_posts
  JOIN wp_term_relationships
    ON wp_term_relationships.object_id = wp_posts.ID
 WHERE term_taxonomy_id = 80
   AND wp_posts.id NOT IN
        ( SELECT object_id
            FROM wp_term_relationships
           WHERE term_taxonomy_id = 109
        )
;

( MySQL 5.6 リファレンス マニュアルの§ 13.2.10.3「、、、または」を使用したサブクエリをANY参照INSOMEください。)

于 2012-09-12T21:01:27.577 に答える
1

1 つのアプローチを次に示します。

SELECT p.*
  FROM wp_posts p
  JOIN wp_term_relationships t
    ON t.object_id = p.ID AND t.term_taxonomy_id = 80
  LEFT
  JOIN wp_term_relationships n
    ON n.object_id = p.ID AND n.term_taxonomy_id = 109
 WHERE n.object_id IS NULL

これは、用語関係テーブル (エイリアスとしてn) に対して LEFT OUTER 結合を使用して、カテゴリ内の一致する行を見つけます109が、一致が見つかった行を除外します (WHERE句の条件を介して、wp_posts から返される行はそれらです)。カテゴリ 109 に含まれないもの。

SQL 用語では、この操作を「アンチ JOIN」と呼びます。

注: このクエリは、一意でない場合、「重複」行を返す可能性があり(object_id,term_taxonomy_id)ます。たとえば、wp_term_relationships に (object_id=2,term_taxonomy_id=80) の行が 2 つ (またはそれ以上) ある場合です。


一般に、MySQL では、JOIN 操作 (結合防止操作を含む) がサブクエリよりもパフォーマンスが優れていることがよくあります。

別の代替手段 (前のクエリほど実行されない可能性が高い):

SELECT p.*
  FROM wp_posts p
 WHERE EXISTS 
       ( SELECT 1 
           FROM wp_term_relationships t
          WHERE t.object_id = p.ID 
            AND t.term_taxonomy_id = 80
        )
   AND NOT EXISTS 
       ( SELECT 1 
           FROM wp_term_relationships n
          WHERE n.object_id = p.ID 
            AND n.term_taxonomy_id = 109
        )

注: MySQL は、このクエリに対して前のクエリと同じ実行プラン (結合操作と反結合操作を含む) を生成する可能性があります。クエリで EXPLAIN を実行して実行計画を確認し、一方が他方よりも「速い」かどうかをテストする必要があります。

他のアプローチもあります。パフォーマンスは、利用可能な (適切な) インデックス、データ分散、および生成された実行計画に依存します。

于 2012-09-12T21:14:04.770 に答える
0

これは、集計クエリとして実行できます。このアプローチが好きなのは、グループ内の要素を定義するのに最も柔軟だと思うからです。

select id
from wp_posts p JOIN
     wp_term_relationships t
     ON t.object_id = p.ID
group by id
having sum(case when term_taxonomy_id = 80 then 1 else 0 end) > 0 and    -- in 80
       sum(case when term_taxonomy_id = 109 then 1 else 0 end) = 0       -- not in 109
于 2012-09-12T21:24:52.640 に答える