[wp-trac] [WordPress Trac] #48280: orderby meta_value breaks with newer versions of MySQL

WordPress Trac noreply at wordpress.org
Thu Oct 10 19:01:27 UTC 2019


#48280: orderby meta_value breaks with newer versions of MySQL
---------------------------+-----------------------------
 Reporter:  KodieGrantham  |      Owner:  (none)
     Type:  defect (bug)   |     Status:  new
 Priority:  normal         |  Milestone:  Awaiting Review
Component:  Query          |    Version:  5.2.3
 Severity:  normal         |   Keywords:
  Focuses:                 |
---------------------------+-----------------------------
 When running a query like this:
 {{{#!php
 <?php
 $posts = new WP_Query(array(
   'post_type'           => 'course_record',
   'posts_per_page'      => -1,
   'orderby'             => 'meta_value',
   'meta_key'            => 'start_date'
 ));
 ?>
 }}}

 which results in the following SQL query:
 {{{#!sql
 SELECT   wp_posts.* FROM wp_posts  INNER JOIN wp_postmeta ON ( wp_posts.ID
 = wp_postmeta.post_id ) WHERE 1=1  AND ( wp_postmeta.meta_key =
 'start_date' ) AND wp_posts.post_type = 'course_record' AND
 (wp_posts.post_status = 'publish') GROUP BY wp_posts.ID ORDER BY
 wp_postmeta.meta_value DESC
 }}}

 On MySQL v5.7.25, it works fine and returns posts as expected.
 On MySQL v8.0.16, it returns zero posts without any errors.

 The weird thing is, if I try to run the SQL statement from above directly
 into the MySQL console '''on either MySQL version''', I get the following
 error:
 {{{#!text
 ERROR 1055 (42000): Expression #1 of ORDER BY clause is not in GROUP BY
 clause and contains nonaggregated column
 'wp_artofed.wp_postmeta.meta_value' which is not functionally dependent on
 columns in GROUP BY clause; this is incompatible with
 sql_mode=only_full_group_by
 }}}

 I also get the same error if I try the SQL statement directly in PHP
 outside of WordPress '''again, on either MySQL version''':
 {{{#!php
 <?php
 $conn = new mysqli($db_host, $db_user, $db_pass, $db_name);
 if ($conn->connect_error) die("Connection failed: $conn->connect_error");
 if (!$results = $conn->query("SELECT   wp_posts.* FROM wp_posts  INNER
 JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1  AND (
 wp_postmeta.meta_key = 'start_date' ) AND wp_posts.post_type =
 'course_record' AND (wp_posts.post_status = 'publish') GROUP BY
 wp_posts.ID ORDER BY wp_postmeta.meta_value DESC")) {
   die("Query Error: $conn->error");
 }
 ?>
 }}}

 However it works if I use `$wpdb->get_results` '''on MySQL v5.7.25''' but
 not v8.0.16:
 {{{#!php
 <?php
 global $wpdb;
 $results = $wpdb->get_results("SELECT   wp_posts.* FROM wp_posts  INNER
 JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1  AND (
 wp_postmeta.meta_key = 'start_date' ) AND wp_posts.post_type =
 'course_record' AND (wp_posts.post_status = 'publish') GROUP BY
 wp_posts.ID ORDER BY wp_postmeta.meta_value DESC");
 ?>
 }}}

 I was able to get everything working however by adding
 `wp_postmeta.meta_value` to the `GROUP BY` clause:
 {{{#!php
 <?php
 add_filter('posts_groupby', 'fix_wp_only_full_group_by', 10, 2);
 function fix_wp_only_full_group_by($groupby, $query) {
   if (
     !empty($groupby) &&
     array_key_exists('orderby', $query->query_vars) &&
     $query->query_vars['orderby'] === 'meta_value'
   ) {
     global $wpdb;
     $groupby .= ", {$wpdb->postmeta}.meta_value";
   }
   return $groupby;
 }
 ?>
 }}}

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/48280>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list