Search code examples
phpmysqlsqlwordpresssubquery

WordPress Subquery returns more than 1 row on SELECT


I am executing this query with core cron by custom Wordpress plugin:

// MAKE SQL CALL
    $SQL = "SELECT ".$wpdb->prefix."postmeta.post_id FROM ".$wpdb->prefix."postmeta
    INNER JOIN ".$wpdb->prefix."posts ON (".$wpdb->prefix."posts.ID = ".$wpdb->prefix."postmeta.post_id )       
     WHERE ".$wpdb->prefix."postmeta.meta_key = '".$core_admin_values['listing_expiration']['key']."' 
     AND ".$wpdb->prefix."posts.post_status = 'publish'
     AND ".$wpdb->prefix."postmeta.post_id = (SELECT ".$wpdb->prefix."postmeta.post_id FROM ".$wpdb->prefix."postmeta WHERE ".$wpdb->prefix."postmeta.meta_key = 'listing_status' AND ".$wpdb->prefix."postmeta.meta_value != 1)
     AND ".$wpdb->prefix."posts.post_type = '".$core_admin_values['listing_expiration']['taxonomy']."_type'
     AND DATE(".$wpdb->prefix."postmeta.meta_value) < DATE(NOW())";     
    $expired_listings = (array)$wpdb->get_results($SQL);

But return this error:

FastCGI sent in stderr: "PHP message: Database error of WordPress Subquery returns more than 1 row for SELECT

How to solve this? I tried some solutions by similar problems here in Stack, but it still fails.


Solution

  • For the sake of legibility I reformatted your query.

    SELECT 
      postmeta.post_id 
    FROM 
      postmeta
      INNER JOIN posts 
        ON (posts.ID = postmeta.post_id )       
    WHERE 
      postmeta.meta_key = '".$core_admin_values['listing_expiration']['key']."' 
      AND posts.post_status = 'publish'
      AND postmeta.post_id = 
      (
          SELECT 
            postmeta.post_id 
          FROM 
            postmeta 
          WHERE 
            postmeta.meta_key = 'listing_status' 
            AND postmeta.meta_value != 1
      )
      AND posts.post_type = '".$core_admin_values['listing_expiration']['taxonomy']."_type'
      AND DATE(postmeta.meta_value) < DATE(NOW())";     
    

    I suspect your issue stems from the subquery in your where clause.

          SELECT 
            postmeta.post_id 
          FROM 
            postmeta 
          WHERE 
            postmeta.meta_key = 'listing_status' 
            AND postmeta.meta_value != 1
    

    And that this chunk is returning more than one result. If you want to match against more than one result, change from "=" to "in" like so:

      AND postmeta.post_id in
      (
          SELECT 
            postmeta.post_id ...
      )