{"id":21629,"date":"2022-10-24T14:40:18","date_gmt":"2022-10-24T21:40:18","guid":{"rendered":"https:\/\/coderpad.io\/?p=21629"},"modified":"2023-06-05T14:00:12","modified_gmt":"2023-06-05T21:00:12","slug":"sql-functions-and-techniques-every-data-person-should-know","status":"publish","type":"post","link":"https:\/\/coderpad.io\/blog\/development\/sql-functions-and-techniques-every-data-person-should-know\/","title":{"rendered":"SQL Functions and Techniques Every Data Person Should Know"},"content":{"rendered":"\n<p>Writing SQL queries that don&#8217;t utilize database features can cost developers a lot. The cost varies from spending more time writing tedious long queries or having a tech debt later on to debug the performance issue coming from the database server.<\/p>\n\n\n\n<p>PostgreSQL has features that help you select data efficiently. These features can also help minimize the lines you write SQL queries.<\/p>\n\n\n\n<p>In a previous tutorial, we discussed why and how to use <a href=\"https:\/\/coderpad.io\/blog\/development\/window-functions-aggregate-data-postgres\/\">window functions<\/a> in PostgreSQL to aggregate data. However, this tutorial will show you what&#8217;s beyond aggregate functions, especially with the HAVING clause. You will also learn about subqueries and different types of JOINs.<\/p>\n\n\n\n<p>Afterward, you will get familiar with features in PostgreSQL, like inheritance, full-text search, views, and how to handle geospatial data in PostgreSQL.<\/p>\n\n\n\n<p>I encourage you to apply everything mentioned in this tutorial. You can use the <a href=\"https:\/\/app.coderpad.io\/sandbox?language=postgresql\">CoderPad sandbox<\/a> with the PostgreSQL playground to practice the commands learned in this article.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Aggregate functions (with <\/strong><strong>HAVING<\/strong><strong> clause)<\/strong><\/h2>\n\n\n\n<p>An aggregate function is a function that groups a number of rows to form one record. Examples of aggregate functions in SQL are <code>MAX<\/code>, <code>MIN<\/code>, <code>COUNT<\/code>, and <code>SUM<\/code>. To filter the output of the aggregated result, you need a <code>HAVING<\/code> clause.<\/p>\n\n\n\n<p>The <code>HAVING<\/code> clause is similar to the <code>WHERE<\/code> clause but for aggregate functions. To make it more clear, see the examples below!<\/p>\n\n\n\n<p>An employee table has been created for the example queries in this section. Have a look at the <code>employees<\/code> table first before proceeding:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee8fb3307.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Employees table<\/figcaption><\/figure>\n<\/div>\n\n\n<p>In the <code>employees<\/code> table above, you want to count the number of employees in each department.<\/p>\n\n\n\n<p>You can use a <code>GROUP BY<\/code> clause for aggregation:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> department_id, <span class=\"hljs-keyword\">count<\/span>(*) <span class=\"hljs-keyword\">AS<\/span> num_employees\n<span class=\"hljs-keyword\">FROM<\/span> employees\n<span class=\"hljs-keyword\">GROUP<\/span> <span class=\"hljs-keyword\">BY<\/span> department_id;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee9185f17.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Number of employees in each department.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>The number of employees in each department designated by their ID is shown in the image above.<\/p>\n\n\n\n<p>What if you want to get the number of employees in the engineering department?<\/p>\n\n\n\n<p>To answer this question, first, retrieve the id of the engineering department from the department table using this query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> *\n<span class=\"hljs-keyword\">FROM<\/span> departments;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee91f3e4f.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">IDs of departments in the database.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>From the image above, the engineering department id is 2. If you filter the <code>department_id<\/code> that equals 2 in the first query, you&#8217;ll get the number of employees in the engineering department:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> department_id, <span class=\"hljs-keyword\">count<\/span>(*) <span class=\"hljs-keyword\">AS<\/span> num_employees\n<span class=\"hljs-keyword\">FROM<\/span> employees\n<span class=\"hljs-keyword\">GROUP<\/span> <span class=\"hljs-keyword\">BY<\/span> department_id\n<span class=\"hljs-keyword\">HAVING<\/span> department_id = <span class=\"hljs-number\">2<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee92899f3.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Number of employees in the engineering department.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>See another example where you want to get all departments where we have just a single employee. To do that, run this query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> department_id, <span class=\"hljs-keyword\">count<\/span>(*) <span class=\"hljs-keyword\">AS<\/span> num_employees\n<span class=\"hljs-keyword\">FROM<\/span> employees\n<span class=\"hljs-keyword\">GROUP<\/span> <span class=\"hljs-keyword\">BY<\/span> department_id\n<span class=\"hljs-keyword\">HAVING<\/span> <span class=\"hljs-keyword\">count<\/span>(*) = <span class=\"hljs-number\">1<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee9326520.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Departments with a single employee.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>So the previous two queries showed how to use the <code>HAVING<\/code> clause. This is the clause we use to filter an aggregate function. The <code>HAVING<\/code> clause is followed by an aggregate condition. You can filter the column name by using <code>=<\/code>, <code>&lt;<\/code>, <code>&gt;<\/code>, or any <a href=\"https:\/\/www.postgresql.org\/docs\/current\/functions-comparison.html\" target=\"_blank\" rel=\"noopener\">comparison operator<\/a>. You can also use an aggregate function in that condition, like the <code>count()<\/code> function in the previous query.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Subqueries<\/strong><\/h2>\n\n\n\n<p>Sometimes your queries must have more than one <code>SELECT<\/code> statement. In such cases, you need <em>subqueries<\/em>.<\/p>\n\n\n\n<p>Suppose you want to get employees&#8217; salaries that are higher than the average. So you go ahead and get the average salary:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> <span class=\"hljs-keyword\">AVG<\/span>(salary)\n<span class=\"hljs-keyword\">FROM<\/span> employees;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee93e53b0.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Average salary in the employees table.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>and then take note of that number and put it in this query:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> *\n<span class=\"hljs-keyword\">FROM<\/span> employees\n<span class=\"hljs-keyword\">WHERE<\/span> salary &gt; <span class=\"hljs-number\">35000<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The problem in this process is that you have an intermediate step. You want to get rid of that manual step and do a one-query. That&#8217;s why you need a subquery which is, in this case, an internal query to calculate the average salary so that you can filter by it. Use a subquery as follows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> *\n<span class=\"hljs-keyword\">FROM<\/span> employees\n<span class=\"hljs-keyword\">WHERE<\/span> salary &gt; (\n\u00a0 <span class=\"hljs-keyword\">SELECT<\/span> <span class=\"hljs-keyword\">AVG<\/span>(salary)\n\u00a0 <span class=\"hljs-keyword\">FROM<\/span> employees\n);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So now selecting the average has become a subquery that we filtered the salary column with.<\/p>\n\n\n\n<p>The previous two queries provide the same output:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee94684f0.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Employees with salary greater than the average.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>You can also use subqueries to check the existence of records instead of filtering their values. Suppose you want to get employees who are not currently working on a project. You have two tables, employees and <code>employees_projects<\/code>. The latter table references each employee with their corresponding projects. Run <code>SELECT *<\/code> from each table to take a look!<\/p>\n\n\n\n<p>Then, you could write a query like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> e.first_name, e.last_name, e.salary\n<span class=\"hljs-keyword\">FROM<\/span> employees e\n<span class=\"hljs-keyword\">WHERE<\/span> e.id <span class=\"hljs-keyword\">NOT<\/span> <span class=\"hljs-keyword\">IN<\/span> (\n\u00a0 <span class=\"hljs-keyword\">SELECT<\/span> ep.employee_id\n\u00a0 <span class=\"hljs-keyword\">FROM<\/span> employees_projects ep\n\u00a0 <span class=\"hljs-keyword\">WHERE<\/span> e.id = ep.employee_id\n);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This query gets the employee data where the employee ID does not exist in the list of values of <code>employee_id<\/code>&#8216;s in the <code>employees_projects<\/code> table. This is not a very efficient query if you have a table with million records. That&#8217;s because you wouldn&#8217;t need the <code>employee_id<\/code>&#8216;s values. Here you just need to check if they exist or not. In this case, you&#8217;ll need to return true values from the <code>employees_projects<\/code> table, which can be used by <code>SELECT<\/code> 1. You&#8217;ll also need to use the keyword <code>EXISTS<\/code> to check the existence of these true values. For our query, we would negate the existence using the <code>NOT<\/code> operator.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> e.first_name, e.last_name, e.salary\n<span class=\"hljs-keyword\">FROM<\/span> employees e\n<span class=\"hljs-keyword\">WHERE<\/span> <span class=\"hljs-keyword\">NOT<\/span> <span class=\"hljs-keyword\">EXISTS<\/span> (\n\u00a0 <span class=\"hljs-keyword\">SELECT<\/span> <span class=\"hljs-number\">1<\/span>\n\u00a0 <span class=\"hljs-keyword\">FROM<\/span> employees_projects ep\n\u00a0 <span class=\"hljs-keyword\">WHERE<\/span> e.id = ep.employee_id\n);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The previous two queries provide the same output:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee94b9781.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Employee not present in the <code>employees_projects<\/code> table.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>As you can see, <strong>John Mills<\/strong> is the only employee who doesn&#8217;t have an ongoing project to work on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Self joins<\/strong><\/h2>\n\n\n\n<p>A self-join is used to join columns from the same table.<\/p>\n\n\n\n<p>Let\u2019s assume you want to retrieve employees who share the same last name:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> e1.id, e1.first_name, e2.last_name\n<span class=\"hljs-keyword\">FROM<\/span> employees e1, employees e2\n<span class=\"hljs-keyword\">WHERE<\/span> e1.id &lt;&gt; e2.id\n<span class=\"hljs-keyword\">AND<\/span> e1.last_name = e2.last_name;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>FROM<\/code> clause is followed by two tables; the same employees table. There are two conditions in the <code>WHERE<\/code> clause; ids are not the same, and the last names are the same.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee9550ad5.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Employees sharing the same last name.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>The above short-hand comma syntax is equivalent to an <code>INNER JOIN<\/code> syntax (which we will illustrate later in this tutorial). So an equivalent query would be:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> e1.id, e1.first_name, e2.last_name\n<span class=\"hljs-keyword\">FROM<\/span> employees e1\n<span class=\"hljs-keyword\">JOIN<\/span> employees e2 <span class=\"hljs-keyword\">ON<\/span> e1.last_name = e2.last_name\n<span class=\"hljs-keyword\">AND<\/span> e1.id &lt;&gt; e2.id;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\"><strong>OUTER joins<\/strong><\/h2>\n\n\n\n<p>An <code>OUTER<\/code> join is the <code>FULL_OUTER_JOIN<\/code>. This join returns all records that meet the query condition, whether in the left table or in the right table.<\/p>\n\n\n\n<p>To make sure you understand <code>OUTER<\/code> joins, experiment with the example below.<\/p>\n\n\n\n<p>Assume you have a record inserted in the employees table that has an empty value in a specific column like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">INSERT<\/span> <span class=\"hljs-keyword\">INTO<\/span> employees(first_name, last_name, salary) <span class=\"hljs-keyword\">VALUES<\/span>(<span class=\"hljs-string\">'Ibrahim'<\/span>, <span class=\"hljs-string\">'Saeid'<\/span>, <span class=\"hljs-number\">15000<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As you can see, Ibrahim Saied is added with a salary equal to 15000 but there was a little issue. He was not assigned to any department. In other words, the value of <code>department_id<\/code> in his record is <code>NULL<\/code>. Have a look at the new employees table running <code><strong>SELECT * FROM<\/strong> employees<\/code>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee95a4feb.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Updated employees list<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Have a second look at the departments table, and you&#8217;ll see that there is a department that has no employees, which is Biz Dev, with an id of 4. That&#8217;s because <code>department_id<\/code> has no value of 4 in the <code>employees<\/code> table.<\/p>\n\n\n\n<p>Our task now is to list all employees&#8217; names associated with their departments.<\/p>\n\n\n\n<p>You can accomplish different outcomes to solve this task. You need to know what requirements you really want to accomplish. In this section and the section that follows, we will discuss different scenarios.<\/p>\n\n\n\n<p>You need two tables; employees table to get employees names, and departments table to get departments names. That&#8217;s a given! but there are null values in each table!<\/p>\n\n\n\n<p>To list all employees with their departments, including both Ibrahim Saeid and the Biz Dev department, use <code>FULL OUTER JOIN<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> e.first_name, e.last_name, e.salary, d.name <span class=\"hljs-keyword\">AS<\/span> department\n<span class=\"hljs-keyword\">FROM<\/span> employees e\n<span class=\"hljs-keyword\">FULL<\/span> <span class=\"hljs-keyword\">OUTER<\/span> <span class=\"hljs-keyword\">JOIN<\/span> departments d <span class=\"hljs-keyword\">ON<\/span> d.id = e.department_id;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee960a75a.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">List of employees including their departments.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>In the next section, we will discuss more scenarios.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>INNER joins<\/strong><\/h2>\n\n\n\n<p>An <code>INNER<\/code> join is the conventional SQL join. This join statement joins two tables that match on both sides, the left and right tables.<\/p>\n\n\n\n<p>An <code>INNER<\/code> join has 3 types:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>INNER JOIN<\/code> which returns all records that match the values in both tables<\/li>\n\n\n\n<li><code>LEFT INNER JOIN<\/code> which returns all records that meet the query condition in the left table, but doesn&#8217;t meet that condition in the right table<\/li>\n\n\n\n<li><code>RIGHT INNER JOIN<\/code> which is the reverse of the <code>LEFT OUTER JOIN<\/code><\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>\ud83d\udca1You can omit the <code>INNER<\/code> keyword from each join statement.<\/p>\n<\/blockquote>\n\n\n\n<p>So in the <code>OUTER<\/code> join query example mentioned in the last section, we saw that both null values, from the employees table and the departments table, were returned. For the <code>INNER JOIN<\/code>, the case is the reverse. You&#8217;ll get records that exist in <em>both<\/em> tables:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> e.first_name, e.last_name, e.salary, d.name <span class=\"hljs-keyword\">AS<\/span> department\n<span class=\"hljs-keyword\">FROM<\/span> employees e\n<span class=\"hljs-keyword\">JOIN<\/span> departments d <span class=\"hljs-keyword\">ON<\/span> d.id = e.department_id;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee965e417.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">Employees existing in both tables.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>As you can see, there are no null values that match the join condition.<\/p>\n\n\n\n<p>To list all employees with their departments, including Ibrahim Saeid, who is not in a department:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> e.first_name, e.last_name, e.salary, d.name <span class=\"hljs-keyword\">AS<\/span> department\n<span class=\"hljs-keyword\">FROM<\/span> employees e\n<span class=\"hljs-keyword\">LEFT<\/span> <span class=\"hljs-keyword\">JOIN<\/span> departments d <span class=\"hljs-keyword\">ON<\/span> d.id = e.department_id;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, we used <code>LEFT JOIN<\/code> because we started selecting the employees table. So the output would be:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee96c5695.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">List of employees with and without a department.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>To list employees with their departments, <em>including<\/em> the Biz Dev department, which has no employees, just change the previous query from <code>LEFT JOIN<\/code> to <code>RIGHT JOIN<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql shcb-wrap-lines\"><span class=\"hljs-keyword\">SELECT<\/span> e.first_name, e.last_name, e.salary, d.name <span class=\"hljs-keyword\">AS<\/span> department\n<span class=\"hljs-keyword\">FROM<\/span> employees e\n<span class=\"hljs-keyword\">RIGHT<\/span> <span class=\"hljs-keyword\">JOIN<\/span> departments d <span class=\"hljs-keyword\">ON<\/span> d.id = e.department_id;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2022\/10\/img_6356ee9728d8d.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">List of employees with their departments<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Run the sandbox below to test the new queries learned in this article:<\/p>\n\n\n<div\n\tclass=\"sandbox-embed responsive-embed  sandbox-embed--full-width\"\n\tstyle=\"padding-top: 125%\"\ndata-block-name=\"coderpad-sandbox-embed\">\n\t<iframe src=\"https:\/\/embed.coderpad.io\/sandbox?question_id=232788&#038;use_question_button\" width=\"640\" height=\"800\" loading=\"lazy\" aria-label=\"Try out the CoderPad sandbox\"><\/iframe>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>The mentioned PostgreSQL features can help you write fewer lines of SQL and also write performant queries. Learning these concepts in PostgreSQL will help you in your PostgreSQL interview questions to write queries.<\/p>\n\n\n\n<p>This tutorial discussed how to write aggregate functions (with a <code>HAVING<\/code> clause). We saw how to write subqueries and use them efficiently. You learned how to use self-joins, outer joins, and inner joins (including left and right joins).<\/p>\n\n\n\n<p>You should also take a look at <a href=\"https:\/\/coderpad.io\/blog\/development\/postgresql-system-catalogs-metadata\/\">PostgreSQL System Catalogs<\/a>, which is an advanced topic on PostgreSQL data analysis.<\/p>\n\n\n\n<p><em>I\u2019m Ezz. I\u2019m an AWS Certified Machine Learning Specialist and a Data Platform Engineer. I help SaaS companies rank on Google. Check out my&nbsp;<a href=\"https:\/\/ezzeddinabdullah.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">website<\/a>&nbsp;for more.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Writing SQL queries that don&#8217;t utilize database features can cost developers a lot. This article covers SQL functions and techniques every data person should know in detail, alongside examples of how to use them.<\/p>\n","protected":false},"author":1,"featured_media":21683,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[],"persona":[29],"blog-programming-language":[66,67],"keyword-cluster":[],"class_list":["post-21629","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/21629","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/comments?post=21629"}],"version-history":[{"count":57,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/21629\/revisions"}],"predecessor-version":[{"id":32648,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/21629\/revisions\/32648"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media\/21683"}],"wp:attachment":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media?parent=21629"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/categories?post=21629"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/tags?post=21629"},{"taxonomy":"persona","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/persona?post=21629"},{"taxonomy":"blog-programming-language","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/blog-programming-language?post=21629"},{"taxonomy":"keyword-cluster","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/keyword-cluster?post=21629"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}