ทำไม 'GROUP BY` ใน hook_views_query_alter () ไม่ทำงาน


11

ฉันใช้ Views 7.x-3.6 และฉันพยายามแก้ไขGROUP BYclause ด้วย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 core hook ( 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

หากต้องการหลีกเลี่ยงการจัดกลุ่มตามเงื่อนไขที่ไม่จำเป็นให้เพิ่ม:

$query->distinct = TRUE;

1
เราจะลบกลุ่มที่ไม่จำเป็นออกได้อย่างไรโดยไม่ต้องเพิ่ม $ query-> different = TRUE;
ARUN

ฉันใช้เวลาไม่กี่ชั่วโมงในการดีบักกลุ่มการดู แต่ปัจจุบันฉันไม่รู้วิธีแก้ปัญหาอื่น
milkovsky

ขอบคุณสำหรับความคิดเห็นของคุณ อืม .. ฉันกำลังถามเพราะถ้าเราเพิ่ม $ query-> different = TRUE; จากนั้นจะเพิ่มnidกับกลุ่มโดย มันไม่จำเป็นสำหรับฉัน ตัวเลือกอื่น ๆ ? คุณรู้วิธีเพิ่มที่ไม่ซ้ำในแบบสอบถามการดู?
ARUN

มันอยู่views_handler_filter::query()ไกล ลอง$query->distinct();ในhook_query_alter
milkovsky

1

ไปงานเลี้ยงสาย แต่สิ่งนี้อาจช่วยคนอื่นได้

ในกรณีของฉันฉันให้รายชื่อผู้ใช้ (โดยใช้โมดูล Profile2 เพิ่มเติม) พร้อมกับฟิลด์ Taxonomy Term ( 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]);
  }
}

ฉันพบข้อผิดพลาดเกี่ยวกับการไม่สามารถจัดกลุ่มตาม

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

หากคุณดูเป็นเอกสารประกอบของhook_views_query_alterฉันเชื่อว่าแบบสอบถามได้เตรียมพร้อมที่จะเรียกใช้แล้ว ตัวอย่างเช่นการแทนที่ถูกสร้างขึ้นโดย API ฐานข้อมูลและกำลังจะถูกส่งผ่านสายไปยัง MySQL อีกตัวอย่างของการใช้ hook_views_query_alter สามารถมองเห็นบล็อก

นี่เป็นกรณีที่คุณไม่มี DB Query Object อีกต่อไป แต่ชิ้นส่วนของคำสั่ง SQL ที่มีนิพจน์ตัวแปร ฯลฯ เป็น Array

ฉันไม่ได้มีแบบสอบถามต่อหน้าฉัน แต่สิ่งที่ต้องการรหัสที่ยังไม่ผ่านการทดสอบต่อไปนี้คือสิ่งที่คุณต้องการ:

$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.