Чому `GROUP BY` у куці_вигляди_query_alter () не працює?


11

Я використовую Views 7.x-3.6, і я спробував змінити GROUP BYпункт, hook_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-> razloct = TRUE;
АРУН

Я витратив кілька годин на налагодження групи переглядів. Але наразі я не знаю іншого рішення.
мілковський

Дякуємо за ваш коментар хм .. я прошу, тому що, якщо додати $ query-> razloct = ІСТИНА; тоді він додасть nidз групою по. Мені це не потрібно. Будь-який інший варіант? Чи знаєте ви, як додати унікальний запит на перегляди?
АРУН

Це було по- views_handler_filter::query()справжньому. Спробуйте $query->distinct();вhook_query_alter
мілковський

1

Пізно на вечірку, але це може допомогти комусь іншому.

У моєму випадку я надав список користувачів (використовуючи додатковий модуль Profile2) з полем Термін Таксономія ( https://drupal.org/node/1808320 ). Я бачив кілька результатів, від яких не міг позбутися за допомогою API Views 3.

У свій спеціальний модуль я додав:

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

поле, яке насправді є результатом COUNT()функції SQL .

Я закінчився цим:

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

Якщо ви дивитесь, що це документація на зачіпку_перегляду_запрошення , я вважаю, що запит вже готовий до запуску. Наприклад, заміни були зроблені API бази даних, і він вже буде відправлений по протоколу до MySQL. Ще один приклад використання пристосування_підписки_query_alter можна побачити в блозі BTMash .

У цьому випадку у вас більше немає об’єкта запитів БД, але фрагменти оператора SQL з виразами, змінними тощо як масив.

У мене немає запиту перед собою, але щось подібне до наступного неперевіреного коду - це те, що ви хочете:

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

Дякую за вашу відповідь! Я спробував, але і це не працює: знову ж, $queryоб’єкт змінено (інакше, ніж вище, звичайно), але знову ж таки, SQL-запит не змінюється!
jozi

ви спробували гачок іншого виду? _pre_render чи _pre_build? .... Я б спробував гак_все_пре_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');
    }
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.