Warum funktioniert `GROUP BY` in hook_views_query_alter () nicht?


11

Ich verwende Views 7.x-3.6 und habe versucht, die GROUP BYKlausel hook_views_query_alter()wie folgt zu ändern :

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

Wenn ich nachschaue $query, ist die groupbyKlausel korrekt aktiviert, aber die SQL-Abfrage ist nicht betroffen : Die GROUP BYKlausel wird nicht angezeigt:

Geben Sie hier die Bildbeschreibung ein

Was ich schließlich getan habe, ist die Verwendung eines Drupal-Core-Hooks ( hook_query_alter()) und es hat gut funktioniert: Das SQL ist jetzt betroffen.

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

Gibt es einen Grund, warum mein hook_views_query_alter()nicht funktioniert? Ich frage mich, ob es einen saubereren Weg gibt und.

Antworten:


11

Verwenden Sie add_field()mit array('function' => 'groupby')Parametern.

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

Zusätzliche Informationen:

Nach der Verwendung add_groupbywird möglicherweise der folgende Code angezeigt GROUP BY:

GROUP BY node.nid, nid

Siehe die nächste Ausgabe: https://drupal.org/node/1578808

Um unnötige GROUP BY-Bedingungen zu vermeiden, fügen Sie Folgendes hinzu:

$query->distinct = TRUE;

1
Wie können wir unnötige Gruppen entfernen, indem wir $ query-> unique = TRUE hinzufügen?
— ARUN

Ich habe einige Stunden damit verbracht, Ansichten von zu debuggen. Aber derzeit kenne ich keine andere Lösung.
— Milkovsky

Vielen Dank für Ihren Kommentar. hmm .. ich frage weil, wenn wir $ query-> unique = TRUE hinzufügen; dann wird es nidmit group by hinzugefügt . Es ist für mich nicht notwendig. Irgendeine andere Option? Wissen Sie, wie Sie eine eindeutige Abfrage in Ansichten hinzufügen können?
— ARUN

Es war views_handler_filter::query()fair. Versuchen Sie $query->distinct();inhook_query_alter
— Milkovsky

1

Spät zur Party, aber das könnte jemand anderem helfen.

In meinem Fall habe ich eine Liste der Benutzer (unter Verwendung des zusätzlichen Moduls Profile2) mit einem Feld für den Taxonomiebegriff ( https://drupal.org/node/1808320 ) bereitgestellt . Ich habe mehrere Ergebnisse gesehen, die ich über die Views 3-API nicht entfernen konnte.

In meinem benutzerdefinierten Modul habe ich hinzugefügt:

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

  }
}

Die Parameter für add_field sind

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

1

Wenn Sie immer noch mit unnötigen GROUP BY-Anweisungen konfrontiert sind, die der Abfrage hinzugefügt wurden, können Sie diese entfernen hook_query_alter(). Ich habe das Problem gelöst, indem ich beispielsweise Kommentare von den meisten kommentierten Elternkommentaren bestellt habe.

Also in habe hook_views_query_alter()ich:

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

Ich habe einen Fehler im Zusammenhang mit der Unfähigkeit, nach zu gruppieren

comment_count

Feld, das tatsächlich ein Ergebnis der SQL- COUNT()Funktion ist.

Am Ende hatte ich Folgendes:

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

Wenn Sie sich die Dokumentation von hook_views_query_alter ansehen , ist die Abfrage meines Erachtens bereits für die Ausführung vorbereitet. Beispielsweise wurden Ersetzungen durch die Datenbank-API vorgenommen und werden bald über die Leitung an MySQL gesendet. Ein weiteres Beispiel für die Verwendung von hook_views_query_alter ist der BTMash-Blog .

In diesem Fall haben Sie kein DB-Abfrageobjekt mehr, sondern die Teile der SQL-Anweisung mit Ausdrücken, Variablen usw. als Array.

Ich habe keine Abfrage vor mir, aber so etwas wie der folgende ungetestete Code ist das, was Sie wollen:

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

Danke für deine Antwort! Ich habe es versucht, aber es funktioniert auch nicht: Auch hier wird das $queryObjekt geändert (natürlich anders als oben), aber auch hier ändert sich die SQL-Abfrage nicht!
— jozi

Hast du einen anderen Views Hook ausprobiert? _pre_render oder _pre_build? .... ich würde versuchen hook_views_pre_execute () ... api.drupal.org/api/views/views.api.php/function/…
— tenken

0

So wird es in views_query_alter gemacht; Der Teil node_access ist nicht erforderlich.

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

Ich fragte mich, dass niemand eine echte Lösung lieferte, die einfach funktioniert. Es gibt eine solche Methode, die ich hier gefunden habe , vielen Dank an @ 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

In Drupal 8 und dank graceman9 Ansatz wird es sein:

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');
    }
  }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.