web-dev-qa-db-ja.com

添付ファイルがないすべての投稿をクエリすることは可能ですか?

添付ファイルのないすべての投稿の一覧を取得して削除します。

この質問持っている添付ファイルがあるすべての投稿を取得することについて取りますが、私はそれの逆を望みます。

それをするための強引な方法は、すべての投稿を取得し、それらを個別にループ処理してから、添付があるかどうかを確認することです。しかし可能ならば避けたい。

7
Sudar

添付ファイルなしですべての投稿を見つけるSQLの方法に興味がありました。

方法1 - NOT INを使ったサブクエリ

これが私の最初の試みです。

global $wpdb;            
$sql = "
    SELECT  p1.ID, p1.post_title         
    FROM    {$wpdb->posts} p1
    WHERE   p1.post_type = 'post'
        AND p1.post_status = 'publish' 
        AND p1.ID NOT IN ( 
                SELECT DISTINCT p2.post_parent
                FROM {$wpdb->posts} p2
                WHERE p2.post_type = 'attachment' AND p2.post_parent > 0  
        ) 
    ORDER BY p1.post_date DESC
";

// Fetch posts without attachments:
$posts_without_attachments = $wpdb->get_results( $sql );

// Display posts without attachments:
foreach( $posts_without_attachments as $post )
{
        echo $post->post_title . '<br/>';
}

これは、@ toschoのクエリと非常によく似ていますが、構文の合理化はそれほど進んでいません。

方法2 - LEFT JOINIS NULL

このクエリも同様に機能するようです。

global $wpdb;            
$sql = "
    SELECT  p1.ID, p1.post_title
    FROM {$wpdb->posts} p1 
    LEFT JOIN {$wpdb->posts} p2 
    ON ( p2.post_parent = p1.ID AND p2.post_type = 'attachment' )
    WHERE p1.post_type =  'post' 
    AND p1.post_status =  'publish'
    AND p2.post_parent IS NULL 
    ORDER BY p1.post_date DESC
";

// Fetch posts without attachments:
$posts_without_attachments = $wpdb->get_results( $sql );

ここでpostsテーブルとそれ自身を結合してから、添付ファイルの親列のNULL行を選びます。

方法#3 - posts_whereフィルターを持つWP_Query、別名方法#1

posts_whereフィルタでWP_Query()を修正することもできます。

// Filter all posts without attachments:
add_filter( 'posts_where', 'wpse_no_attachments' );

// Query:
$q = new WP_Query( array( 'post_type' => 'post', 'posts_per_page' => -1 ) );

// Remove the filter:
remove_filter( 'posts_where', 'wpse_no_attachments' );

ここで、

function wpse_no_attachments( $where )
{
    global $wpdb;
    $where .= " AND {$wpdb->posts}.ID NOT IN (
                    SELECT DISTINCT wpse.post_parent
                    FROM {$wpdb->posts} wpse
                    WHERE wpse.post_type = 'attachment' AND wpse.post_parent > 0  ) ";
    return $where;
}
4
birgire

リンクされた答えと正反対のことに満足している場合は、添付ファイルを持つすべての投稿を取得して、そのIDをpost__not_in\WP_Queryパラメータとして使用するだけで、このクエリを使用できます。

$attachment_args = array( 
  'post_type'      => 'attachment',
  'post_mime_type' => 'image',
  'post_status' => 'inherit',
  'posts_per_page' => -1,
  'post_parent__not_in' => array(0),
  'meta_query' => array(
    array(
      'key' => '_thumbnail_id',
      'value' => 'x',
      'compare' => 'NOT EXISTS'
    )
  ),
  'fields' => 'post_parent'
);
$atts = new WP_Query($args);
$parents = array_unique(wp_list_pluck($atts->posts,'post_parent'));

$post_args = array(
    'post_type'      => 'post',
    'posts_per_page' => -1
    'post__not_in'   => $parent 
    'post_status'    => 'any'
);
// Posts with no attachment:
$post_query = new WP_Query( $post_args );

更新 Toschoは、この1つのクエリを作成するように指示しました。そしてもちろん、これは1つのプレーンなSQLクエリで処理できます。

<?php 
$query = <<<SQL
    SELECT p.`ID` FROM {$wpdb->posts} p 
    WHERE p.`post_type` = 'post'
    AND p.`post_status` = 'publish'
    AND p.`ID` NOT IN (
        SELECT DISTINCT a.`post_parent` FROM {$wpdb->posts} a 
        WHERE a.`post_type` = 'attachment'
        AND a.`post_parent` != 0
    )
SQL;

//posts with no attachment
$results = $GLOBALS[ 'wpdb' ]->get_results( $query );

このクエリは画像とサムネール後の画像の間に違いを生じさせず、またあらゆる種類の添付ファイルを探すため、これは参照された回答から得られたバリアントとはわずかに異なります。

5
David