Tại sao `GROUP BY` trong hook_view_query_alter () không hoạt động?


11

Tôi đang sử dụng Lượt xem 7.x-3.6 và tôi đã thử thay đổi GROUP BYmệnh đề hook_views_query_alter()như dưới đây:

function mymodule_views_query_alter(&$view, &$query) {
    if ($view->name == "view_name"){
      $query->add_groupby('field_name');
      dpm($query);    
    }
}

Khi tôi nhìn vào $query, các groupbykhoản được kích hoạt một cách chính xác nhưng các truy vấn SQL không bị ảnh hưởng : các GROUP BYđiều khoản không xuất hiện:

nhập mô tả hình ảnh ở đây

Điều cuối cùng tôi đã làm là sử dụng hook core Drupal ( hook_query_alter()) và nó hoạt động tốt: SQL hiện bị ảnh hưởng.

function mymodule_query_alter(QueryAlterableInterface $query) {
  $view_name = 'view_name';
  if ($query->hasTag('views_' . $view_name)) {    
    $query->groupBy('field_name');
  }
}

Bất kỳ lý do tại sao của tôi hook_views_query_alter()không làm việc? Tôi tự hỏi nếu có một cách sạch hơn để làm điều đó và.

Câu trả lời:


11

Sử dụng add_field()với array('function' => 'groupby')tham số.

$query->add_field('node', 'nid', 'node_nid', array('function' => 'groupby'));
$query->add_groupby('node.nid');

Thêm thông tin:

Sau khi sử dụng, add_groupbybạn có thể thấy mã tiếp theo sau GROUP BY:

GROUP BY node.nid, nid

Xem vấn đề tiếp theo: https://drupal.org/node/1578808

Để tránh các điều kiện NHÓM không cần thiết, hãy thêm:

$query->distinct = TRUE;

1
Làm cách nào chúng ta có thể xóa nhóm không cần thiết bằng cách không thêm $ query-> differ = TRUE;
ARUN

Tôi đã dành vài giờ gỡ lỗi nhóm xem. Nhưng hiện tại tôi không biết giải pháp khác.
milkovsky

Cám ơn bạn đã góp ý. hmm .. tôi đang hỏi bởi vì, nếu chúng ta thêm $ query-> differ = TRUE; sau đó nó sẽ thêm nidvới nhóm theo. Nó không cần thiết cho tôi. Còn lựa chọn nào khác không? Bạn có biết làm thế nào để thêm duy nhất trong truy vấn lượt xem?
ARUN

Đó là views_handler_filter::query()afair. Hãy thử $query->distinct();tronghook_query_alter
milkovsky

1

Đi dự tiệc muộn nhưng điều này có thể giúp đỡ người khác.

Trong trường hợp của tôi, tôi đã cung cấp một danh sách người dùng (sử dụng mô-đun bổ sung Profile2) với trường Thuật ngữ phân loại ( https://drupal.org/node/1808320 ). Tôi đã thấy nhiều kết quả mà tôi không thể thoát khỏi API Lượt xem 3.

Trong mô-đun tùy chỉnh của tôi, tôi đã thêm:

/**
    Implementation of hook_views_query_alter()
**/
function MYMODULE_views_query_alter(&$view, &$query) {

  if($view->name == "provider_results_list" && $view->current_display == "page_1") {

    $query->distinct = TRUE;

    // User the provider uid to make the results distinct: using a taxonomy field for
    // keyword searches brings up multiple results. 
    $query->add_field('profile', 'uid', 'provider_uid', array('function' => 'groupby'));

  }
}

Các tham số cho add_field là

add_field(TABLE_NAME, FIELD, FIELD_ALIAS, array('function' => 'groupby'))

1

Nếu bạn vẫn phải đối mặt với các câu lệnh GROUP BY không cần thiết được thêm vào truy vấn, bạn có thể xóa chúng trong hook_query_alter() . Tôi đã giải quyết vấn đề bằng cách đặt bình luận bằng hầu hết các bình luận của phụ huynh.

Vì vậy, trong hook_views_query_alter()tôi có:

/**
 * Implements hook_views_query_alter().
 */
function MODULENAME_views_query_alter(&$view, &$query) {
  if ($view->name == 'reviews' && $query->orderby[0]['field'] == 'comment_thread') {
    $join = new views_join;
    $join->construct('comment', 'comment', 'cid', 'pid', NULL, 'LEFT');
    $query->add_relationship('c1', $join, 'comment');
    $query->add_field('comment', 'pid', 'c1_pid', array('function' => 'groupby'));
    $query->add_groupby('c1.pid');
    $query->add_orderby(NULL, 'COUNT(c1.cid)', 'DESC', 'comments_count');
    $query->distinct = TRUE;
    $query->orderby[0] = $query->orderby[count($query->orderby) - 1];
    unset($query->orderby[count($query->orderby) - 1]);
  }
}

Tôi gặp lỗi liên quan đến việc không thể nhóm

bình luận

trường thực sự là kết quả của SQL COUNT() hàm .

Tôi đã kết thúc với điều này:

/**
 * Implements hook_query_alter().
 */
function MODULENAME_query_alter(QueryAlterableInterface $query) {
  if (isset($query->alterMetaData['view']->name) && $query->alterMetaData['view']->name == 'reviews') {
    $fields =& $query->getGroupBy();
    foreach (array_keys($fields) as $key) {
      // Remove group by statements from generated query which were actually not set in view query.
      if (!in_array($key, $query->alterMetaData['view']->query->groupby)) {
        unset($fields[$key]);
      }
    }
  }
}

0

Nếu bạn xem tài liệu của hook_view_query_alter , tôi tin rằng truy vấn đã được chuẩn bị để chạy. Ví dụ, các thay thế đã được API cơ sở dữ liệu thực hiện và nó sẽ được gửi qua dây tới MySQL. Một ví dụ khác về việc sử dụng hook_view_query_alter có thể được xem blog BTMash .

Đây là trường hợp bạn không còn có Đối tượng truy vấn DB mà là các phần của câu lệnh SQL với các biểu thức, biến, v.v. dưới dạng một mảng.

Tôi không có một truy vấn trước mặt tôi nhưng một cái gì đó giống như mã chưa được kiểm tra sau đây là những gì bạn muốn:

$query->groupby[0]['field'] = 'field_name';

Cảm ơn câu trả lời của bạn! Tôi đã thử nhưng nó cũng không hoạt động: một lần nữa, $queryđối tượng bị thay đổi (tất nhiên khác với ở trên) nhưng một lần nữa, truy vấn SQL không thay đổi!
jozi

bạn đã thử một cái móc quan điểm khác nhau? _pre numnder, hay _pre_build? .... Tôi sẽ thử hook_view_pre_execute () ... api.drupal.org/api/view/view.api.php/feft/ Kẻ
tenken

0

Đây là cách nó được thực hiện trong lượt xem_query_alter; phần node_access là không cần thiết.

function xdas_target_audience_views_query_alter(&$view, &$query) {
  $controlled_views = variable_get('xdas_target_audience_views', array(
    'landing_products',
    'promotions',
    'landing_coupons',
    'landing_coupons_belvita',
    'landing_coupons_lulu',
    'related_coupon',
    'cuponazo',
    'banner',
    'brands',
  ));
  if (in_array($view->name, $controlled_views) && $view->base_table == 'node') {
    //add node_access to views so we can control access.
    $query->add_tag('node_access');
    $join = new views_join();
    $join->construct('xdas_target_audience_boost', 'node', 'nid', 'nid');        
    $query->add_relationship('xdas_target_audience_boost', $join, 'node');
    $query->add_field('xdas_target_audience_boost', 'score', 'score' , array('function' => 'max'));
    $query->add_orderby(NULL, NULL, 'DESC', 'score');   
    $query->add_groupby('nid');    
  }
}

0

Tôi tự hỏi rằng không ai cung cấp một giải pháp thực sự chỉ hoạt động. Có một phương pháp mà tôi đã tìm thấy ở đây , rất cám ơn @ b-ravanbakhsh:

/**
 * Implements hook_query_alter().
 */
function MODULENAME_query_alter(QueryAlterableInterface $query) {
  if (isset($query->alterMetaData['view'])) {
    if($query->alterMetaData['view']->name == 'YOUR_VIEW_NAME'){
      // also you can unset other group by critera by using, unset($query->getGroupBy());
      $query->groupBy('users.uid');
    }
  }
}

0

Trong Drupal 8 và nhờ cách tiếp cận graceman9, nó sẽ là:

use Drupal\Core\Database\Query\AlterableInterface;

function MYMODULE_query_alter(AlterableInterface $query) {
  if (isset($query->alterMetaData['view'])) {
    if($query->alterMetaData['view']->id() == 'replace_by_view_machine_name') {
      // Group by UID to remove duplicates from View results
      $query->groupBy('users_field_data.uid');
      // If multilingual site, you should add the following
      // $query->groupBy('users_field_data.langcode');
    }
  }
}
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.