hook_views_query_alter ()의`GROUP BY`가 작동하지 않는 이유는 무엇입니까?


11

Views 7.x-3.6을 사용하고 있으며 다음 GROUP BYhook_views_query_alter()같이 절을 변경하려고했습니다 .

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

내가에서 볼 때 $query, 절은 올바르게 설정되어 있지만 SQL 쿼리는 영향을받지 않습니다 다음 절은 표시되지 않습니다 :groupbyGROUP BY

여기에 이미지 설명을 입력하십시오

내가 결국 한 것은 Drupal 코어 후크 ( hook_query_alter())를 사용하는 것이며 정상적으로 작동했습니다. SQL이 이제 영향을받습니다.

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

hook_views_query_alter()작동하지 않습니까? 더 깔끔한 방법이 있는지 궁금합니다.

답변:


11

매개 변수 add_field()와 함께 사용하십시오 array('function' => 'groupby').

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

추가 정보 :

사용 후 add_groupby다음 코드가 표시 될 수 있습니다 GROUP BY.

GROUP BY node.nid, nid

다음 호 참조 : https://drupal.org/node/1578808

불필요한 GROUP BY 조건을 피하려면 다음을 추가하십시오.

$query->distinct = TRUE;

1
$ query-> distinct = TRUE를 추가하지 않고 불필요한 그룹을 어떻게 제거 할 수 있습니까?
ARUN

뷰 그룹을 디버깅하는 데 몇 시간을 보냈습니다. 그러나 현재 다른 솔루션을 모르겠습니다.
milkovsky

귀하의 의견에 감사드립니다. 흠 .. 우리가 $ query-> distinct = TRUE를 추가하면 묻습니다. nid그룹별로 추가 됩니다. 나를 위해 필요하지 않습니다. 다른 옵션이 있습니까? 고유 한 조회 조회를 추가하는 방법을 알고 있습니까?
ARUN

그것은 views_handler_filter::query()공정했다. 시도 $query->distinct();hook_query_alter
milkovsky

1

파티에 늦었지만 다른 사람을 도울 수 있습니다.

필자의 경우 Taxonomy Term 필드 ( https://drupal.org/node/1808320 ) 가있는 사용자 목록 (추가 모듈 Profile2 사용)을 제공하고 있었습니다. Views 3 API를 통해 제거 할 수없는 여러 결과가 나타났습니다.

내 맞춤 모듈에서 다음을 추가했습니다.

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

  }
}

add_field의 매개 변수는

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

1

쿼리에 불필요한 GROUP BY 문이 추가되어있는 경우에서에서 제거 할 수 있습니다 hook_query_alter(). 예를 들어 대부분의 주석이 달린 부모 의견으로 주석을 주문하는 문제를 해결했습니다.

그래서 hook_views_query_alter()나는 가지고있다 :

/**
 * 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]);
  }
}

그룹화 할 수없는 오류와 관련하여 오류가 발생했습니다.

comments_count

실제로 SQL COUNT()함수 의 결과 인 필드입니다 .

나는 이것으로 끝났다.

/**
 * 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

hook_views_query_alter 의 문서를 보면 쿼리를 이미 실행할 준비가 된 것 같습니다. 예를 들어, 데이터베이스 API에 의해 대체가 이루어졌으며 MySQL을 통해 유선으로 전송 될 예정입니다. hook_views_query_alter 사용법의 다른 예는 BTMash 블로그에서 볼 수 있습니다 .

DB 쿼리 개체가 더 이상 없지만 표현식, 변수 등을 배열로 사용하는 SQL 문 조각이 더 이상없는 경우입니다.

내 앞에 쿼리가 없지만 테스트되지 않은 다음 코드와 같은 것이 당신이 원하는 것입니다.

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

답변 주셔서 감사합니다! 시도했지만 작동하지 않습니다. 다시, $query객체가 변경됩니다 (물론 위와 다릅니다). 그러나 다시 SQL 쿼리는 변경되지 않습니다!
jozi

다른 견해를 시도 했습니까? _pre_render 또는 _pre_build? .... 나는 hook_views_pre_execute ()를 시도 할 것이다 ... api.drupal.org/api/views/views.api.php/function/…
tenken

0

이것은 views_query_alter에서 수행되는 방식입니다. node_access 부분은 필요하지 않습니다.

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

아무도 실제로 작동하는 실제 솔루션을 제공하지 않았는지 궁금합니다. 내가 찾은 것이 하나 개의 방법이 여기에 , @의 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

Drupal 8에서는 graceman9 접근 방식 덕분에 다음과 같습니다.

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');
    }
  }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.