Perché `GROUP BY` in hook_views_query_alter () non funziona?


11

Sto usando Views 7.x-3.6 e ho provato a modificare la GROUP BYclausola hook_views_query_alter()come di seguito:

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

Quando guardo dentro $query, la groupbyclausola è abilitata correttamente ma la query SQL non è interessata : la GROUP BYclausola non appare:

inserisci qui la descrizione dell'immagine

Quello che alla fine ho fatto è stato usare un hook core di Drupal ( hook_query_alter()) e ha funzionato bene: l'SQL è ora interessato.

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

Qualche motivo per cui il mio hook_views_query_alter()non funziona? Mi chiedo se esiste un modo più pulito per farlo e.

Risposte:


11

Utilizzare add_field()con array('function' => 'groupby')parametro

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

Informazioni aggiuntive:

Dopo l'uso add_groupbypotresti vedere il codice seguente dopo GROUP BY:

GROUP BY node.nid, nid

Vedi il prossimo numero: https://drupal.org/node/1578808

Per evitare inutili condizioni GROUP BY aggiungere:

$query->distinct = TRUE;

1
Come possiamo rimuovere un gruppo non necessario senza aggiungere $ query-> distinto = VERO;
ARUN,

Ho passato alcune ore a eseguire il debug del gruppo di visualizzazioni. Ma al momento non conosco altra soluzione.
milkovsky,

Grazie per il tuo commento. hmm .. te lo chiedo perché, se aggiungiamo $ query-> distinto = VERO; quindi aggiungerà nidcon il gruppo per. Non è necessario per me Qualche altra opzione? Sai come aggiungere query uniche nelle viste?
ARUN,

E ' views_handler_filter::query()andata male. Prova $query->distinct();ahook_query_alter
milkovsky

1

In ritardo alla festa, ma questo potrebbe aiutare qualcun altro.

Nel mio caso stavo fornendo un elenco di utenti (utilizzando il modulo aggiuntivo Profile2) con un campo Termine tassonomia ( https://drupal.org/node/1808320 ). Stavo vedendo più risultati di cui non potevo liberarmi tramite l'API di Views 3.

Nel mio modulo personalizzato ho aggiunto:

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

  }
}

I parametri per add_field sono

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

1

Se stai ancora affrontando istruzioni GROUP BY non necessarie aggiunte alla query, puoi rimuoverle hook_query_alter(). Ho risolto il problema con l'ordinazione dei commenti dalla maggior parte dei commenti dei genitori commentati, ad esempio.

Quindi hook_views_query_alter()ho:

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

Ho riscontrato un errore relativo all'impossibilità di raggruppare

comments_count

campo che è in realtà un risultato della COUNT()funzione SQL .

Ho finito con questo:

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

Se guardi sono la documentazione di hook_views_query_alter , credo che la query sia già pronta per essere eseguita. Ad esempio, l'API del database ha effettuato sostituzioni e sta per essere inviata via cavo a MySQL. Un altro esempio di utilizzo di hook_views_query_alter è il blog di BTMash .

In questo caso non hai più un oggetto query DB ma i pezzi dell'istruzione SQL con espressioni, variabili, ecc. Come matrice.

Non ho una domanda davanti a me ma qualcosa come il seguente codice non testato è quello che vuoi:

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

Grazie per la tua risposta! Ho provato ma non funziona neanche: di nuovo, l' $queryoggetto viene modificato (diversamente da quanto sopra ovviamente) ma, di nuovo, la query SQL non cambia!
jozi,

hai provato un gancio diverso vista? _pre_render o _pre_build? .... Proverei hook_views_pre_execute () ... api.drupal.org/api/views/views.api.php/function/…
tenken

0

Questo è il modo in cui viene fatto in views_query_alter; la parte node_access non è necessaria.

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

Mi chiedevo che nessuno fornisse una soluzione reale che funzionasse. C'è un metodo del genere che ho trovato qui , grazie a @ 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 e grazie all'approccio graceman9, sarà:

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');
    }
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.