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 2014年

私はグループ化されたビューのデバッグに数時間を費やしました。しかし、現在私は他の解決策を知りません。
milkovsky 2014年

ご意見をありがとうございます。うーん.. $ query-> distinct = TRUE;を追加すると、その後nid、グループで追加されます。私には必要ありません。他のオプションはありますか?ビュークエリに一意を追加する方法を知っていますか?
ARUN 2014年

それはviews_handler_filter::query()不公平だった。試し$query->distinct();hook_query_alter
milkovsky

1

パーティーに遅れますが、これは他の誰かを助けるかもしれません。

私の場合、ユーザーのリストに(追加モジュールProfile2を使用して)分類用語フィールド(https://drupal.org/node/1808320)を提供していました。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]);
  }
}

グループ化できないことに関連するエラーが発生しました

コメント数

実際には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 2013年

別のビューフックを試しましたか?_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

誰もがうまく機能する実際のソリューションを提供していないのではないかと思いました。私がここで見つけた方法が1つあります。@ 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.