Hello

I almost tried every combination of getting these views to work. The most difficult thing is, that I do use three connection between nodes:

node.vid -> author.vid for Version
and
mybook.authorid -> author.id (1:1 connection between author and mybook)
and
bookcollection.id -> (mybookbookcollectionrel.bookcollectionid | mybookcollectionrel.mybookid)
-> mybook.id (n:m relation between mybook and bookcollection over a relation table)

The correct SQL generated by views 2.0 would be the following:
SELECT author.name AS authorname, bookcollection.vid AS bookcollectionvid, bookcollection.name AS bookcollectionname, mybook.vid AS mybook_vid, mybook.title AS mybooktitle
FROM node node
LEFT JOIN author author ON node.vid = author.vid
LEFT JOIN bookcollection bookcollection_node ON node.vid = bookcollection_node.vid
LEFT JOIN mybook mybook_node ON node.vid = mybook_node.vid
INNER JOIN mybook mybook ON mybook.authorid = author.id
LEFT JOIN mybookbookcollectionrel mybookbookcollectionrel ON mybook.id = mybookbookcollectionrel.mybookid
LEFT JOIN bookcollection bookcollection ON bookcollection.id = mybookbookcollectionrel.bookcollectionid

I need 3 Joins on the node and the entites mybook, bookcollection, and author over vid (ensures newest version)
Then I need an INNER JOIN between mybook and author (getting all books of an author)
And at least I need a double join over the relation table: mybook.id -> mybookbookcollectionrel -> bookcollection.id
(getting all bookcollection of mybooks)

Unfortunately the SQL Code generated is always faulty. Where is my fault in the mymodule.views.inc.

I commented out all the joins because they had no influence on the resulting SQL Query statement.

<?

/**

CREATE TABLE `author` (
`nid` int(10) NOT NULL,
`vid` int(10) NOT NULL,
`id` int(10) NOT NULL,
`name` varchar(120) NOT NULL,
PRIMARY KEY (`id`),
KEY `vid` (`vid`),
KEY `nid` (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `bookcollection` (
`nid` int(10) NOT NULL,
`vid` int(10) NOT NULL,
`id` bigint(20) NOT NULL,
`authorid` bigint(20) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
KEY `authorid` (`authorid`),
KEY `nid` (`nid`),
KEY `vid` (`vid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `mybookbookcollectionrel` (
`mybookid` bigint(20) NOT NULL default '0',
`bookcollectionid` bigint(20) NOT NULL default '0',
KEY `bookcollectionid` (`bookcollectionid`),
KEY `mybookid` (`mybookid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `mybook` (
`nid` int(10) NOT NULL,
`vid` int(10) NOT NULL,
`id` bigint(20) NOT NULL,
`authorid` bigint(20) NOT NULL default '0',
`title` varchar(150) NOT NULL,
`content` text,
PRIMARY KEY (`id`),
KEY `authorid` (`authorid`),
KEY `nid` (`nid`),
KEY `vid` (`vid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

//---- Notations ---//
- an author can have on or more books

- books can be grouped into bookcollections
- a bookcollection are mybook from the same author

- mybook can be in several more bookcollection.
- a bookcollection consists of one ore more mybooks

The link between mybook and bookcollection is done by mybookbookcollectionrel which is only a relation-table

- a mybook is linked 1:1 with an author
- a mybook collection is linked with an author

//---- SQL Query Test -----//

The goal is a view that looks like that:

authorname | bookcollection_name | mybook_title |
AAA | 1 | Title 1
AAA | 1 | Title 2
AAA | 1 | Title 3
AAA | 1 | Title 4
AAA | 2 | Title 1
AAA | 2 | Title 2
AAA | 2 | Title 5
AAA | 2 | Title 6

With arguments I could show only one bookcollection (argument on bookcollectionid)

//---- SQL Queries from Views 2.0 ---- //

SELECT node.nid AS nid,
author_mybook.name AS author_mybook_name,
bookcollection.name AS bookcollection_name,
mybook.vid AS mybook_vid,
mybook.title AS mybook_title
FROM node node
LEFT JOIN mybook mybook ON node.vid = mybook.vid
INNER JOIN author author_mybook ON mybook.authorid = author_mybook.id
LEFT JOIN mybook mybook_mybookbookcollectionrel ON .mybookid = mybook_mybookbookcollectionrel.
LEFT JOIN bookcollection bookcollection ON node.vid = bookcollection.vid
WHERE bookcollection.vid = 201

The SQL Code is not valid that is generated by Views 2.0. There are missing table names and fields.

//---- SQL Queries that would be correct --//
SELECT author.name AS authorname, bookcollection.vid AS bookcollectionvid, bookcollection.name AS bookcollectionname, mybook.vid AS mybook_vid, mybook.title AS mybooktitle
FROM node node
LEFT JOIN author author ON node.vid = author.vid
LEFT JOIN bookcollection bookcollection_node ON node.vid = bookcollection_node.vid
LEFT JOIN mybook mybook_node ON node.vid = mybook_node.vid
INNER JOIN mybook mybook ON mybook.authorid = author.id
LEFT JOIN mybookbookcollectionrel mybookbookcollectionrel ON mybook.id = mybookbookcollectionrel.mybookid
LEFT JOIN bookcollection bookcollection ON bookcollection.id = mybookbookcollectionrel.bookcollectionid

I need 3 Joins on the node and the entites mybook, bookcollection, and author
Then I need an INNER JOIN between mybook and author
And at least I need a double join over the relation table: mybook.id -> mybookbookcollectionrel -> bookcollection.id

*/

/**
 * Implementation of hook_views_data()
 */
function mymodule_author_views_data() {
	
	$data = array();
	
	
	// Basic table information.
	
	// Define the base group of this table. Fields that don't
	// have a group defined will go into this field by default.
	$data['author']['table']['group']  = t('mymodule');

	$data['author']['table']['base'] = array(
		'field' => 'id',
    	'title' => t('Bookcollection'),
    );
		
	
	// For other base tables, explain how we join
	$data['author']['table']['join'] = array(
		// author links to node directly via vid.	
		'node' => array(
			'left_field' => 'vid',
			'field' => 'vid',
		 ),
	);
	
	///ALBUM
	$data['bookcollection']['table']['group']  = t('mymodule');

	// For other base tables, explain how we join
	$data['bookcollection']['table']['join'] = array(
		
		// author links to node directly via vid.	
		'node' => array(
			'left_field' => 'vid',
			'field' => 'vid',
		 ),
		/*
		'author' => array(
			'left_field' => 'authorid',
			'field' => 'id',
		 ),
		 'mybookbookcollectionrel' => array(
			'left_field' => 'id',
			'field' => 'bookcollectionid',
		 ),
		 'mybook' => array(
		 	'left_table' => 'mybookbookcollectionrel',
			'left_field' => 'bookcollectionid',
			'field' => 'id',
		 ),*/
	);	
	
	//SONG
	$data['mybook']['table']['group']  = t('mymodule');
	
	// For other base tables, explain how we join
	$data['mybook']['table']['join'] = array(
		// author links to node directly via vid.	
		'node' => array(
			'left_field' => 'vid',
			'field' => 'vid',
		 ),
		/*
		 'author' => array(
		 	'left_field' => 'id',
			'field' => 'authorid',
		 ),
		 'mybookbookcollectionrel' => array(
		    'left_table' => 'mybook',
			'left_field' => 'id',
			'field' => 'mybookid',
		 ),
		 'bookcollection' => array(
		 	'left_table' => 'mybookbookcollectionrel',
			'left_field' => 'bookcollectionid',
			'field' => 'id',
		 ),*/
		 
	);
	
	//SONGREL
	$data['mybookbookcollectionrel']['table']['group']  = t('mymodule');

	
	// For other base tables, explain how we join
	$data['mybookbookcollectionrel']['table']['join'] = array(
		// author links to node directly via vid.	
		/*
		'author' => array(
		 	'left_field' => 'id',
			'field' => 'authorid',
		 ),
		 'bookcollection' => array(
			'left_field' => 'id',
			'field' => 'bookcollectionid',
		 ),*/
		 
	);	
	


  // ----------------------------------------------------------------
  // Fields
  // authorid
  $data['author']['id'] = array(
    'title' => t('Author ID'), // The item it appears as on the UI,
     'help' => t('The Author ID.'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
      'numeric' => TRUE,
      ),
    'argument' => array(
      'handler' => 'views_handler_argument_node_vid',
      'click sortable' => TRUE,
      'numeric' => TRUE,
    ),
    
  );
  
  //author vid
  $data['author']['vid'] = array(
    'title' => t('Author vid'), // The item it appears as on the UI,
     'help' => t('The Author vid.'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
      'numeric' => TRUE,
      ),
    'argument' => array(
      'handler' => 'views_handler_argument_node_vid',
      'click sortable' => TRUE,
      'numeric' => TRUE,
    ),
    'relationship' => array(
      'base' => 'node',
      'field' => 'vid',
      'handler' => 'views_handler_relationship',
      'label' => t('Author Node Relation'),
    ),
  );
  
  // authorname
  $data['author']['name'] = array(
    'title' => t('Author Name'), // The item it appears as on the UI,
     'help' => t('The Author Name.'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
     ),
    'sort' => array(
      'handler' => 'views_handler_sort',
    ),
  );

  
  // Bookcollection ID
  $data['bookcollection']['id'] = array(
    'title' => t('Bookcollection ID'), // The item it appears as on the UI,
     'help' => t('The bookcollection id'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
     ),
    'relationship' => array(
      'base' => 'mybookbookcollectionrel',
      'field' => 'bookcollectionid',
      'handler' => 'views_handler_relationship',
      'label' => t('Bookcollection Mybook Relation'),
    ),    
 );

   // Bookcollection ID
  $data['bookcollection']['authorid'] = array(
    'title' => t('Bookcollections Author ID'), // The item it appears as on the UI,
     'help' => t('The bookcollections author id'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
     ),
    'relationship' => array(
      'base' => 'author',
      'field' => 'id',
      'handler' => 'views_handler_relationship',
      'label' => t('Bookcollection Author Relation'),
    ),    
 );
 
    // Bookcollection: Node vid
  $data['bookcollection']['vid'] = array(
    'title' => t('Bookcollection vid'), // The item it appears as on the UI,
     'help' => t('The bookcollection vid'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
     ),
   'argument' => array(
      'handler' => 'views_handler_argument_node_vid',
      'click sortable' => TRUE,
      'numeric' => TRUE,
    ),
    'relationship' => array(
      'base' => 'node',
      'field' => 'vid',
      'handler' => 'views_handler_relationship',
      'label' => t('Bookcollection Node Relationship'),
    ),
  );
  
  
  // Bookcollectionname
  $data['bookcollection']['name'] = array(
    'title' => t('Bookcollection Name'), // The item it appears as on the UI,
     'help' => t('The bookcollection name'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
     ),
     'sort' => array(
      'handler' => 'views_handler_sort',
    ),
  );

  // Mybook id
  $data['mybook']['id'] = array(
    'title' => t('Mybook ID'), // The item it appears as on the UI,
     'help' => t('The Mybook ID.'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
      'numeric' => TRUE,
      ),
    'relationship' => array(
      'base' => 'mybookbookcollectionrel',
      'field' => 'mybookid',
      'handler' => 'views_handler_relationship',
      'label' => t('Mybook Bookcollection Relation'),
    ),    
  );  
    
    // Mybook vid
  $data['mybook']['vid'] = array(
    'title' => t('Mybook vid'), // The item it appears as on the UI,
     'help' => t('The Mybook vid.'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
      'numeric' => TRUE,
      ),
    'argument' => array(
      'handler' => 'handler_argument_node_vid',
      'click sortable' => TRUE,
      'numeric' => TRUE,
    ),
    'relationship' => array(
      'base' => 'node',
      'field' => 'vid',
      'handler' => 'views_handler_relationship',
      'label' => t('Mybook Node Relation'),
    ),     
    
  );  

  // Mybook: AuthorId
  $data['mybook']['authorid'] = array(
    'title' => t('Mybooks Author ID'), // The item it appears as on the UI,
     'help' => t('The Mybooks Author ID.'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
      'numeric' => TRUE,
      ),
    'relationship' => array(
      'base' => 'author',
      'field' => 'id',
      'handler' => 'views_handler_relationship',
      'label' => t('Mybook Author Relation'),
    ),     
    
  ); 
  
  
  // Mybook name
  $data['mybook']['title'] = array(
    'title' => t('Mybook Title'), // The item it appears as on the UI,
     'help' => t('The mybook title'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
     ),
     'sort' => array(
      'handler' => 'views_handler_sort',
    ),
  );

  
   // Mybookbookcollectionrel bookcollectionid
  $data['mybookbookcollectionrel']['bookcollectionid'] = array(
    'title' => t('Mybook Bookcollection Relation Bookcollection ID'), // The item it appears as on the UI,
     'help' => t('The mybook bookcollection relation bookcollection id'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
     ),
   'relationship' => array(
   	  'base' => 'bookcollection',
      'field' => 'id',
      'handler' => 'views_handler_relationship',
      'label' => t('Mybook Author Relation'),
    ),  
  );
  
  // Mybookbookcollectionrel mybookid
  $data['mybookbookcollectionrel']['mybookid'] = array(
    'title' => t('Mybook Bookcollection Relation Mybook ID'), // The item it appears as on the UI,
     'help' => t('The mybook bookcollection relation mybook id'), // The help that appears on the UI,
     // Information for displaying a title as a field
    'field' => array(
      'handler' => 'views_handler_field',
      'click sortable' => TRUE,
     ),
   'relationship' => array(
      'base' => 'mybook',
      'field' => 'id',
      'handler' => 'views_handler_relationship',
      'label' => t('Mybook Author Relation'),
    ),  
  );
  


  return $data;
}


?>

Comments

brainski’s picture

Does anyone have a hint for me?

@merlinofchaos: I know, you're extremly busy. But it seems that you are the only one, that can help me...

merlinofchaos’s picture

Here is a custom relationship handler that handles multiple table relationships that works:

<?php

/**
 * Specialized relationship handler to add nodequeues.
 */
class project_handler_relationship_project_project_release_node extends views_handler_relationship {
  /**
   * Called to implement a relationship in a query.
   */
  function query() {
    // Figure out what base table this relationship brings to the party.
    $join = new views_join();
    $join->definition = array(
      'table' => 'project_release_nodes',
      'field' => 'pid',
      'left_table' => 'node',
      'left_field' => 'nid',
    );

    if (!empty($this->options['required'])) {
      $join->definition['type'] = 'INNER';
    }

    $join->construct();

    $this->first_join = = $this->query->add_table('project_release_nodes', $this->relationship, $join);

    // Then, create a relationship on that table:
    $join = new views_join();
    $join->definition = array(
      'left_table' => $this->first_join,
      'left_field' => 'nid',
      'table' => 'node',
      'field' => 'nid',
    );

    if (!empty($this->options['required'])) {
      $join->definition['type'] = 'INNER';
    }

    $join->construct();

    $alias = $join->definition['table'] . '_' . $join->definition['left_table'];

    $this->alias = $this->query->add_relationship($alias, $join, 'project_release_nodes', $this->relationship);
  }
}

  );

  // pid
  $data['project_release_nodes']['pid'] = array(
    'title' => t('Pid'),
    'help' => t('The node ID of the project node a release is tied to.'),
    'field' => array(
      'handler' => 'views_handler_field_node',
      'click sortable' => TRUE,
    ),
    // Information for accepting a nid as an argument
    'argument' => array(
      'handler' => 'views_handler_argument_node_nid',
      'name field' => 'title',
      'numeric' => TRUE,
      'validate type' => 'nid',
    ),
    // Information for accepting a nid as a filter
    'filter' => array(
      'handler' => 'views_handler_filter_numeric',
    ),
    // Information for sorting on a nid.
    'sort' => array(
      'handler' => 'views_handler_sort',
    ),
    'relationship' => array(
      'base' => 'node',
      'field' => 'nid',
      'handler' => 'views_handler_relationship',
      'title' => 'Please work for me.',
    )
  );

  // version
  $data['project_release_nodes']['version'] = array(
    'title' => t('Version string'),
    'help' => t('The full version string of a release.'),
    'field' => array(
      'group' => t('Project release'),
      'handler' => 'views_handler_field_node',
      'click sortable' => TRUE,
     ),
    'sort' => array(
      'handler' => 'views_handler_sort',
    ),
    'filter' => array(
      'handler' => 'views_handler_filter_string',
    ),
    'argument' => array(
      'handler' => 'views_handler_argument_string',
    ),
  );

  // tag
  $data['project_release_nodes']['tag'] = array(
    'title' => t('Tag'),
    'help' => t('The tag associated with a release.'),
    'field' => array(
      'group' => t('Project release'),
      'handler' => 'views_handler_field_node',
      'click sortable' => TRUE,
     ),
    'sort' => array(
      'handler' => 'views_handler_sort',
    ),
    'filter' => array(
      'handler' => 'views_handler_filter_string',
    ),
    'argument' => array(
      'handler' => 'views_handler_argument_string',
    ),
  );

  // @TODO:  file_path
  // @TODO:  file_date
  // @TODO:  file_hash
  // @TODO:  rebuild
  // @TODO:  version_major
  // @TODO:  version_minor
  // @TODO:  version_patch
  // @TODO:  version_extra


  return $data;
}

/**
 * Specialized relationship handler to add nodequeues.
 */
class project_handler_relationship_project_project_release_node extends views_handler_relationship {
  /**
   * Called to implement a relationship in a query.
   */
  function query() {
    // Figure out what base table this relationship brings to the party.
    $join = new views_join();
    $join->definition = array(
      'table' => 'project_release_nodes',
      'field' => 'pid',
      'left_table' => 'node',
      'left_field' => 'nid',
    );

    if (!empty($this->options['required'])) {
      $join->definition['type'] = 'INNER';
    }

    $join->construct();

    $this->first_join = $this->query->add_table('project_release_nodes', $this->relationship, $join);

    // Then, create a relationship on that table:
    $join = new views_join();
    $join->definition = array(
      'left_table' => $this->first_join,
      'left_field' => 'pid',
      'table' => 'node',
      'field' => 'nid',
    );

    if (!empty($this->options['required'])) {
      $join->definition['type'] = 'INNER';
    }

    $join->construct();

    $alias = $join->definition['table'] . '_' . $join->definition['left_table'];

    $this->alias = $this->query->add_relationship($alias, $join, 'project_release_nodes', $this->relationship);
  }
}

/**
 * Implementation of hook_views_data_alter().
 */
function project_release_views_data_alter(&$data) {
  // Project release version information
  $data['node']['bunsen'] = array(
    'group' => t('Project release'),
    'title' => t('Version'),
    'help' => t('Create a relationship to a nodequeue.'),
    'real field' => 'nid',
    'relationship' => array(
      'handler' => 'project_handler_relationship_project_project_release_node',
      'base' => 'node',
      'field' => 'nid',
  );
}

This might help you.

brainski’s picture

Dear merlinofchaos

After 3 days studying and testing your code, I was able to do all these relationships. It was necessary to create my own relationship handlers. But in the end it was working.

Thank you very much for your code sample! I appreciate your help!

merlinofchaos’s picture

Status: Active » Fixed

I'm glad you got it working!

Just FYI, there's a bug in the code I pasted above:

  $this->alias = $this->query->add_relationship($alias, $join, 'project_release_nodes', $this->relationship);

should be:

  $this->alias = $this->query->add_relationship($alias, $join, 'node', $this->relationship);

But otherwise it's working. (You can tell from the comments that this was modified from nodequeue stuff. Yay cut & paste leftovers)

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

ruralrooster’s picture

did you make a module with this? Or where to you upload this handler file? what file name?

leon kessler’s picture

Quite an old thread, but I used the code here to create a relationship handler for double joins. In case anyone needs it.

(Also, would be interested to know if this is done in the "correct" way, in particular defining the additional join data in the field definition).

in includes/yourmodule_handler_double_join_relationship.inc

class yourmodule_handler_double_join_relationship extends views_handler_relationship {
  
  /**
   * Called to implement a relationship in a query.
   */
  function query() {
    
    // Join the second table first.
    $this->ensure_my_table();
    $def = $this->definition;
    
    if (!empty($def['join_handler']) && class_exists($def['join_handler'])) {
      $join = new $def['join_handler'];
    }
    else {
      $join = new views_join();
    }

    $join->definition = array(
      'table' => $def['second table'],
      'field' => $def['second field'],
      'left_table' => $this->table_alias,
      'left_field' => $this->field,
      'type' => !empty($this->options['required']) ? 'INNER' : 'LEFT',
    );
    $join->construct();
    $join->adjusted = TRUE;

    $this->first_join = $this->query->add_table($def['second table'], $this->relationship, $join);
    
    // Figure out what base table this relationship brings to the party.
    $table_data = views_fetch_data($this->definition['base']);
    $base_field = empty($this->definition['base field']) ? $table_data['table']['base']['field'] : $this->definition['base field'];

    if (!empty($def['join_handler']) && class_exists($def['join_handler'])) {
      $join = new $def['join_handler'];
    }
    else {
      $join = new views_join();
    }

    $join->definition = array(
      'table' => $def['base'],
      'field' => $base_field,
      'left_table' => $this->first_join,
      'left_field' => $def['second join field'],
      'type' => !empty($this->options['required']) ? 'INNER' : 'LEFT',
    );
    $join->construct();
    $join->adjusted = TRUE;

    // use a short alias for this:
    $alias = $join->definition['table'] . '_' . $join->definition['left_table'];

    $this->alias = $this->query->add_relationship($alias, $join, $this->definition['base'], $this->relationship);
  }
}

Then to implement this handler for a field, in yourmodule.views.inc

function yourmodule_views_data() {
  ...
  $data['sample_table']['sample_field'] = array(
    'title' => t('Some title'),
    'help' => t('A bit of help here'),  
    'relationship' => array(
      'label' => t('Some label'),
      'help' => t('Performs a double join'),
      'base' => 'users',
      'base field' => 'uid',
      'second table' => 'second_table',
      'second field' => 'second_field',
      'second join field' => 'uid',
      'handler' => 'yourmodule_handler_double_join_relationship',
    ),
}
function yourmodule_views_views_handlers() {
  $handlers = array(
     'info' => array(
     'path' => drupal_get_path('module', 'yourmodule') .'/includes',
    ),
    'handlers' => array(
      'yourmodule_views_handler_double_join_relationship' => array(
        'parent' => 'views_handler_relationship',
      ),
    ),
  );
  return $handlers;
}

So this lets you set all the fields for the double join within the definition of the field relationship.
The above example would give

JOIN second_table ON sample_table.sample_field = second_table.second_field
JOIN users ON users.uid = second_table.uid

kanani’s picture

Issue summary: View changes

added code tags around view