Hive Join & SubQuery Tutorial with Examples

โšก Smart Summary

Hive joins combine rows from two or more tables on a matching column, and subqueries nest one query inside another, so both are demonstrated here on two sample tables loaded from plain text files.

  • ๐Ÿงฑ Two sample tables: sample_joins holds customer details and sample_joins1 holds order details, joined on the shared Id column.
  • ๐Ÿ”— Four join types: Inner, left outer, right outer and full outer joins each keep a different set of unmatched rows.
  • โฌœ NULL marks the gap: An outer join returns a row even with no match, filling every column from the missing side with NULL.
  • ๐Ÿ” Order matters: Joins are not commutative and are left-associative, so swapping the tables changes an outer join result.
  • ๐Ÿงฎ Subqueries nest queries: A subquery is written in the FROM clause or the WHERE clause, and the outer query depends on the value it returns.
  • ๐Ÿ“œ TRANSFORM embeds scripts: Custom map and reduce scripts run through the TRANSFORM clause when no built-in function fits.

Hive join and subquery examples

Join queries

Join queries can be performed on two tables present in Hive. To understand join concepts clearly, we are creating two tables here:

  • sample_joins (related to customer details)
  • sample_joins1 (related to order details placed by employees)

Step 1) Creation of the table “sample_joins” with the column names Id, Name, Age, address and salary of the employees. The screenshot below shows the CREATE TABLE statement and its confirmation.

Hive CREATE TABLE statement for the sample_joins customer table

Step 2) Loading and displaying data. The next screenshot shows the load command followed by the contents of the table.

Loading Customers.txt into sample_joins and displaying the loaded rows

From the above screenshot:

  1. Loading data into sample_joins from Customers.txt
  2. Displaying sample_joins table contents

Step 3) Creation of the sample_joins1 table, then loading and displaying its data, as shown in the screenshot below.

Creating sample_joins1, loading orders.txt and displaying the order rows

From the above screenshot, we can observe the following:

  1. Creation of table sample_joins1 with the columns Orderid, Date1, Id and Amount
  2. Loading data into sample_joins1 from orders.txt
  3. Displaying records present in sample_joins1

Moving forward, we will see the different types of joins that can be performed on the tables we have created. Before that, you have to consider the following points about joins.

Some points to observe in joins:

  • Only equality joins are allowed in joins
  • More than two tables can be joined in the same query
  • LEFT, RIGHT and FULL OUTER joins exist in order to provide more control over the ON clause for which there is no match
  • Joins are not commutative
  • Joins are left-associative irrespective of whether they are LEFT or RIGHT joins

The equality restriction reflects Hive as it was for many years. From Hive 2.2.0 onwards, complex expressions in the ON clause are supported (HIVE-15211), so a non-equality condition is accepted on a current release. On older releases the condition has to be an equality test, with anything else moved into a WHERE clause.

Different type of joins

Joins are of 4 types. These are:

  • Inner join
  • Left outer join
  • Right outer join
  • Full outer join

Each type is demonstrated below against the same two tables, so the only thing that changes between the examples is which unmatched rows survive.

Inner Join

The records common to both tables will be retrieved by this inner join. The result in the screenshot below contains only the customers that have a matching order.

Hive inner join output showing only customers that have a matching order

From the above screenshot, we can observe the following:

  1. Here we are performing a join query using the JOIN keyword between the tables sample_joins and sample_joins1, with the matching condition (c.Id = o.Id).
  2. The output displays the common records present in both tables, selected by checking the condition mentioned in the query.

Query:

SELECT c.Id, c.Name, c.Age, o.Amount FROM sample_joins c JOIN sample_joins1 o ON(c.Id=o.Id);

Left Outer Join

  • HiveQL LEFT OUTER JOIN returns all the rows from the left table even though there are no matches in the right table
  • If the ON clause matches zero records in the right table, the join still returns a record in the result with NULL in each column from the right table

The screenshot below shows that every customer appears, including those with no order.

Hive left outer join output with NULL values for customers without orders

From the above screenshot, we can observe the following:

  1. Here we are performing a join query using the “LEFT OUTER JOIN” keyword between the tables sample_joins and sample_joins1, with the matching condition (c.Id = o.Id). For example, here we are using the employee id as a reference; it checks whether the id is common to the right table as well as the left table. It acts as the matching condition.
  2. The output displays the records selected by the condition mentioned in the query. NULL values in the above output are columns with no values from the right table, that is sample_joins1.

Query:

SELECT c.Id, c.Name, o.Amount, o.Date1 FROM sample_joins c LEFT OUTER JOIN sample_joins1 o ON(c.Id=o.Id)

Right Outer Join

  • HiveQL RIGHT OUTER JOIN returns all the rows from the right table even though there are no matches in the left table
  • If the ON clause matches zero records in the left table, the join still returns a record in the result with NULL in each column from the left table
  • RIGHT joins always return records from the right table and matched records from the left table. If the left table has no value corresponding to the column, it will return NULL values in that place.

The screenshot below shows the mirror image of the previous result: every order appears, matched or not.

Hive right outer join output keeping every order row from sample_joins1

From the above screenshot, we can observe the following:

  1. Here we are performing a join query using the “RIGHT OUTER JOIN” keyword between the tables sample_joins and sample_joins1, with the matching condition (c.Id = o.Id).
  2. The output displays the records selected by checking the condition mentioned in the query.

Query:

  SELECT c.Id, c.Name, o.Amount, o.Date1 FROM sample_joins c RIGHT OUTER JOIN sample_joins1 o ON(c.Id=o.Id)

Full Outer Join

It combines records of both the tables sample_joins and sample_joins1 based on the JOIN condition given in the query.

It returns all the records from both tables and fills in NULL values for the columns whose matching values are missing on either side, as the screenshot below shows.

Hive full outer join output combining unmatched rows from both tables

From the above screenshot, we can observe the following:

  1. Here we are performing a join query using the “FULL OUTER JOIN” keyword between the tables sample_joins and sample_joins1, with the matching condition (c.Id = o.Id).
  2. The output displays all the records present in both tables, selected by checking the condition mentioned in the query. NULL values in the output here indicate the missing values from the columns of both tables.

Query:

SELECT c.Id, c.Name, o.Amount, o.Date1 FROM sample_joins c FULL OUTER JOIN sample_joins1 o ON(c.Id=o.Id)

Sub queries

Joins put tables side by side. A subquery does something different: it nests one query inside another so that the outer query can work from a result that has already been calculated.

A query present within a query is known as a subquery. The main query will depend on the values returned by the subquery.

Subqueries can be classified into two types:

  • Subqueries in the FROM clause
  • Subqueries in the WHERE clause

When to use:

  • To get a particular value combined from two column values from different tables
  • Dependency of one table’s values on other tables
  • Comparative checking of one column’s values against other tables

Syntax:

Subquery in FROM clause
SELECT <column names 1, 2โ€ฆn>From (SubQuery) <TableName_Main >
Subquery in WHERE clause
SELECT <column names 1, 2โ€ฆn> From<TableName_Main>WHERE col1 IN (SubQuery);

Example:

SELECT col1 FROM (SELECT a+b AS col1 FROM t1) t2

Here t1 and t2 are table names. The inner statement is the subquery performed on table t1. Here a and b are columns that are added in the subquery and assigned to col1. Col1 is the column value present in the main table. This column “col1” present in the subquery is equivalent to the main table query in column col1.

Embedding custom scripts

Where a subquery reshapes data with HiveQL alone, an embedded script hands rows to code written outside Hive.

Hive makes it possible to write user-specific scripts for client requirements. Users can write their own map and reduce scripts for those requirements. These are called embedded custom scripts. The coding logic is defined in the custom script, and we can use that script at ETL time.

When to choose embedded scripts:

  • Where client-specific requirements mean developers have to write and deploy scripts in Hive
  • Where Hive built-in functions are not going to work for specific domain requirements

For this, Hive uses the TRANSFORM clause to embed both map and reducer scripts.

In these embedded custom scripts, we have to observe the following points:

  • Columns will be transformed to string and delimited by TAB before being given to the user script
  • Standard output of the user script will be treated as TAB-separated string columns

Sample embedded script:

FROM (
	FROM pv_users
	MAP pv_users.userid, pv_users.date
	USING 'map_script'
	AS dt, uid
	CLUSTER BY dt) map_output

INSERT OVERWRITE TABLE pv_users_reduced
	REDUCE map_output.dt, map_output.uid
	USING 'reduce_script'
	AS date, count;

From the above script, we can observe the following. This is only a sample script for understanding.

  • pv_users is the users table, which has fields such as userid and date as mentioned in map_script
  • The reducer script is defined on the date and count of the pv_users table

FAQs

Historically no. From Hive 2.2.0 complex expressions are allowed in the ON clause (HIVE-15211), so inequality and range conditions work. On earlier releases the ON clause must be an equality test and any other predicate belongs in WHERE.

A map join loads the smaller table into memory and skips the reduce stage entirely. Hive selects it automatically when hive.auto.convert.join is true and the table fits the configured size threshold, which makes small-to-large joins far faster.

It returns rows from the left table that have at least one match on the right, without duplicating them and without returning right-side columns. The right table may only be referenced in the ON clause, not in SELECT or WHERE.

Partly. From Hive 0.13 the IN, NOT IN, EXISTS and NOT EXISTS operators accept subqueries in the WHERE clause, including correlated ones. Restrictions remain, so an unsupported correlation is usually rewritten as a join.

The inner query becomes a derived table, and every table needs a name before its columns can be referenced. That is why the example ends with t2 after the closing bracket; omitting the alias raises a parse error.

When one join key holds a disproportionate share of rows, a single reducer receives most of the work while others idle. Setting hive.optimize.skewjoin, or splitting the heavy key out and unioning the results, spreads the load.

Machine learning assistants read the EXPLAIN plan and flag common causes such as a missing partition filter, an unconverted map join or a skewed key. Treat the suggestion as a starting point and confirm it against the plan and actual runtime.

It drafts standard join and subquery patterns well from a short comment. Verify anything engine-specific, because it readily mixes in Spark SQL or Presto syntax, and Hive rejects constructs such as an unaliased derived table.

Summarize this post with: