Có thể truy vấn tất cả các bài đăng không có tệp đính kèm?


7

Tôi muốn nhận danh sách tất cả các bài đăng không có tệp đính kèm và xóa chúng.

Câu hỏi này cần về việc nhận tất cả các bài đăng tệp đính kèm, nhưng tôi muốn điều ngược lại.

Cách thức mạnh mẽ để làm điều đó là lấy tất cả các bài đăng và sau đó lặp qua chúng một cách riêng lẻ và sau đó kiểm tra xem chúng có đính kèm hay không. Nhưng tôi muốn tránh nó nếu có thể.

Câu trả lời:


4

Tôi tò mò về cách SQL tìm tất cả các bài đăng mà không có bất kỳ tệp đính kèm nào.

Phương pháp # 1 - Truy vấn phụ với NOT IN

Đây là nỗ lực đầu tiên của tôi để xây dựng một truy vấn như vậy:

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/>';
}

Điều này xảy ra rất giống với truy vấn của @ toscho, nhưng ít được sắp xếp hợp lý trong cú pháp ;-)

Phương pháp # 2 - LEFT JOINvớiIS NULL

Truy vấn này dường như cũng hoạt động:

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 );

nơi chúng ta tham gia bảng bài viết với chính nó và sau đó chọn các NULLhàng trong cột cha của tệp đính kèm.

Phương thức # 3 - WP_Query với bộ lọc tests_where aka phương thức # 1

Chúng tôi cũng có thể sửa đổi WP_Query()với posts_wherebộ lọc:

// 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' );

Ở đâu:

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;
}

oh, tôi đã không nhận thấy bản cập nhật SQL trong câu hỏi. Trông rất giống nhau. Phiên bản @ toscho trông có vẻ hợp lý hơn ;-)
birgire

2
Tôi đã gặp sự cố PHPMyAdmin vài lần, khi chơi với GROUP BY vì vậy tôi đã sử dụng DISTINCT thay thế ;-)
birgire

3
Không thể upvote bạn một lần nữa không may :-). Nhưng tôi thích cách tiếp cận thứ hai của bạn tốt hơn.
Pieter Goosen

1
@PieterGoosen cảm ơn, và nó ít mã hơn ;-) @Sudar Tôi đã thêm một cách với một LEFT JOINtruy vấn phụ, vì một số lý do tôi luôn hoài nghi về các truy vấn phụ ;-)
birgire

1
@birgire Cảm ơn và tôi đã đánh dấu đây là câu trả lời. Tôi thích cách tiếp cận thứ 2 và thứ 3.
Sudar

5

Nếu bạn cảm thấy thoải mái với câu trả lời hoàn toàn trái ngược với câu trả lời được liên kết, bạn chỉ cần sử dụng truy vấn này để tìm nạp tất cả các bài đăng có tệp đính kèm và sau đó sử dụng ID của chúng làm post__not_intham số \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 );

Cập nhật Toscho chỉ cho tôi để thực hiện một truy vấn này. Và, tất nhiên, điều này có thể được xử lý với một Truy vấn SQL đơn giản:

<?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 );

Lưu ý rằng điều này hơi khác với biến thể được lấy từ câu trả lời được đề cập vì truy vấn này không tạo ra sự khác biệt giữa hình ảnh và hình thu nhỏ và cũng tìm kiếm bất kỳ loại tệp đính kèm nào.


Cảm ơn. Tôi thường cố gắng sử dụng WP_Querythay vì viết các câu lệnh SQL của riêng mình vì đó là cách được đề xuất. Nhưng tôi đoán đây là một kịch bản đủ phức tạp để đi theo lộ trình câu lệnh SQL.
Sudar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.