Quantcast
Channel: Question and Answer » hook-views-query-alter
Viewing all articles
Browse latest Browse all 26

How JOIN a subselect to main select 'node' fields

$
0
0

For posting purposes, I have removed all sorting, entity relationships, extra fields etc etc from Main View.

Main view returns 1200 rows
Subselect returns 176 rows
After aggregation the main view should display only 176 rows

I am trying to achieve this SQL using views API


SELECT 
    node.nid,
    c.field_parent_component_tid as comp_id, 
    env.field_mig_details_env_tid as env_id,     
    migdate.field_mig_details_mig_date_value AS d

FROM node node

LEFT JOIN field_data_field_parent_component c 
    ON node.nid = c.entity_id     
LEFT JOIN field_data_field_mig_details_env env 
    ON node.nid = env.entity_id 
LEFT JOIN field_data_field_mig_details_mig_date migdate 
    ON node.nid = migdate.entity_id 

JOIN (
      SELECT 
          c_sub.field_parent_component_tid as comp_id, 
          env_sub.field_mig_details_env_tid as env_id,         
          MAX(date_sub.field_mig_details_mig_date_value) AS maxdate

      FROM node subnode

      LEFT JOIN field_data_field_parent_component c_sub 
          ON subnode.nid = c_sub.entity_id           
      LEFT JOIN field_data_field_mig_details_env env_sub
          ON subnode.nid = env_sub.entity_id           
      LEFT JOIN field_data_field_mig_details_mig_date date_sub
          ON subnode.nid = date_sub.entity_id 
      WHERE 
        (subnode.status = '1') 
        AND (subnode.type IN  ('migration_details')) 
        AND (c_sub.field_parent_component_tid IS NOT NULL)

      GROUP BY 
        comp_id,
        env_id
) query2 ON c.field_parent_component_tid = comp_id 
        AND env.field_mig_details_env_tid = env_id
        AND migdate.field_mig_details_mig_date_value = maxdate

So, In hook_views_query_alter(&$view, &$query) I do this code to generate the subselect with all the aggregation


        $subquery = db_select('node', 'subnode');
    //Set up all the joins to get access to the fields    
    $subquery->leftjoin('field_data_field_parent_component', 'c', 'subnode.nid = c.entity_id');
    $subquery->leftjoin('field_data_field_mig_details_mig_date', 'migTbl', 'subnode.nid = migTbl.entity_id');    
    $subquery->leftjoin('field_data_field_mig_details_env', 'e', 'subnode.nid = e.entity_id');
    //now select the fields that will show up on the SELECT statement

    $subquery->fields('c', array('field_parent_component_tid',));
    $subquery->fields('e', array('field_mig_details_env_tid',));

    $subquery->addExpression('MAX(migTbl.field_mig_details_mig_date_value)', 'maxdate');
    //This will generate the WHERE clauses
    $subquery->condition('subnode.status', 1);    
    $subquery->condition('subnode.type', 'migration_details');
    //Lastly the grouping
    $subquery->groupBy('c.field_parent_component_tid, e.field_mig_details_env_tid');
    //Run the query, store in results so I can add it to main query
    $result = $subquery->execute();

Then I add the subselect to the main view with the following code


  $compAlias = $query->tables['node']['field_data_field_parent_component']['alias'];

  $join = new views_join('$subquery', 'node', 'field_parent_component_tid', $compAlias.'.field_parent_component_tid');
  //$join->definition = array('table' => $subquery, 'left_field' => 'field_parent_component_tid', 'field' => 'field_parent_component_tid', 'left_table' => 'node');
  $join->extra_type = 'AND';
  $join->table = $subquery;
  $join->left_field = $compAlias.'.field_parent_component_tid';
  $join->field = 'field_parent_component_tid';
  $join->type = 'INNER';
  //$join->adjusted = true;
  //$join->extra = $WHAT DO I USE HERE??? = field_mig_details_env_tid';
  // AND $WHAT DO I USE HERE??? = maxdate';

  //dpm($join);
  //Add the subquery as another "table" to the main query
  $query->add_relationship('query2', $join, $subquery);

So far so good, the SQL generated in my view looks good, but I need to add an $join->extra whit the equivilant of


AND env.field_mig_details_env_tid = env_id
AND migdate.field_mig_details_mig_date_value = maxdate

If I look at the generated SQL so far it looks like this:


SELECT 
  node.nid AS nid, 
  node_field_data_field_mig_parent_x_ref.nid AS node_field_data_field_mig_parent_x_ref_nid,
  'node' AS field_data_field_parent_component_node_entity_type, 
  'node' AS field_data_field_mig_details_env_node_entity_type, 
  'node' AS field_data_field_mig_details_mig_date_node_entity_type, 
  'node' AS field_data_title_field_node_entity_type
FROM 
 {node} node
LEFT JOIN {field_data_field_mig_parent_x_ref} field_data_field_mig_parent_x_ref 
  ON node.nid = field_data_field_mig_parent_x_ref.entity_id 
  AND (field_data_field_mig_parent_x_ref.entity_type = 'node' 
  AND field_data_field_mig_parent_x_ref.deleted = '0')
LEFT JOIN {node} node_field_data_field_mig_parent_x_ref 
  ON field_data_field_mig_parent_x_ref.field_mig_parent_x_ref_target_id = node_field_data_field_mig_parent_x_ref.nid
INNER JOIN {field_data_field_parent_component} field_data_field_parent_component 
  ON node.nid = field_data_field_parent_component.entity_id 
  AND (field_data_field_parent_component.entity_type = 'node' 
  AND field_data_field_parent_component.deleted = '0')
INNER JOIN (
  SELECT c.field_parent_component_tid AS field_parent_component_tid,    e.field_mig_details_env_tid AS field_mig_details_env_tid,   MAX(migTbl.field_mig_details_mig_date_value) AS maxdate
  FROM 
  {node} subnode
  LEFT OUTER JOIN {field_data_field_parent_component} c ON subnode.nid = c.entity_id
  LEFT OUTER JOIN {field_data_field_mig_details_mig_date} migTbl ON subnode.nid =   migTbl.entity_id
  LEFT OUTER JOIN {field_data_field_mig_details_env} e ON subnode.nid = e.entity_id
  WHERE  (subnode.status = '1') AND (subnode.type = 'migration_details') 
  GROUP BY c.field_parent_component_tid, e.field_mig_details_env_tid) 
query2 ON   
         field_data_field_parent_component.field_parent_component_tid =   query2.field_parent_component_tid
  WHERE (( (node.status = '1') AND (node.type IN  ('migration_details')) AND (field_data_field_parent_component.field_parent_component_tid = '141') ))

If I look at the $query->tables, I don’t see that date table, I don’t see the environement table/ How would I add these??


Viewing all articles
Browse latest Browse all 26

Latest Images

Trending Articles



Latest Images