Implicit Joins

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

(This can also be done while aligning the SQL keywords right.

Another common style is to put important keywords on their own lines:

SELECT
d.Name,
COUNT(*) AS Employees
FROM
Departments AS d
JOIN
Employees AS e
ON d.ID = e.DepartmentID
WHERE
d.Name != 'HR'
HAVING
COUNT(*) > 10
ORDER BY
COUNT(*) DESC;

Vertically aligning multiple similar expressions improves readability:

SELECT Model,
EmployeeID
FROM Cars
WHERE CustomerID = 42
AND Status = 'READY';

Using multiple lines makes it harder to embed SQL commands into other programming languages.
However, many languages have a mechanism for multi-line strings, e.g., @"..." in C#, """...""" in
Python, or R"(...)" in C++.

Joins

Explicit joins should always be used; implicit joins have several problems:

• The join condition is somewhere in the WHERE clause, mixed up with any other filter
conditions. This makes it harder to see which tables are joined, and how.

• Due to the above, there is a higher risk of mistakes, and it is more likely that they are found
later.

• In standard SQL, explicit joins are the only way to use outer joins:

SELECT d.Name,
e.Fname || e.LName AS EmpName
FROM Departments AS d
LEFT JOIN Employees AS e ON d.ID = e.DepartmentID;

• Explicit joins allow using the USING clause:

SELECT RecipeID,

https://riptutorial.com/ 17
Recipes.Name,
COUNT(*) AS NumberOfIngredients
FROM Recipes
LEFT JOIN Ingredients USING (RecipeID);

(This requires that both tables use the same column name.
USING automatically removes the duplicate column from the result, e.g., the join in this
query returns a single RecipeID column.)

Read Clean Code in SQL online: https://riptutorial.com/sql/topic/9843/clean-code-in-sql

https://riptutorial.com/ 18
Chapter 7: Comments
Examples
Single-line comments

Single line comments are preceded by --, and go until the end of the line:

SELECT *
FROM Employees -- this is a comment
WHERE FName = 'John'

Multi-line comments

Multi-line code comments are wrapped in /* ... */:

/* This query
returns all employees */
SELECT *
FROM Employees

It is also possible to insert such a comment into the middle of a line:

SELECT /* all columns: */ *


FROM Employees

Read Comments online: https://riptutorial.com/sql/topic/1597/comments

https://riptutorial.com/ 19
Chapter 8: Common Table Expressions
Syntax
• WITH QueryName [(ColumnName, ...)] AS (
SELECT ...
)
SELECT ... FROM QueryName ...;

• WITH RECURSIVE QueryName [(ColumnName, ...)] AS (


SELECT ...
UNION [ALL]
SELECT ... FROM QueryName ...
)
SELECT ... FROM QueryName ...;

Remarks
Official documentation: WITH clause

A Common Table Expression is a temporary result set, and it can be result of complex sub query.
It is defined by using WITH clause. CTE improves readability and it is created in memory rather
than TempDB database where Temp Table and Table variable is created.

Key concepts of Common Table Expressions:

• Can be used to break up complex queries, especially complex joins and sub-queries.
• Is a way of encapsulating a query definition.
• Persist only until the next query is run.
• Correct use can lead to improvements in both code quality/maintainability and speed.
• Can be used to reference the resulting table multiple times in the same statement (eliminate
duplication in SQL).
• Can be a substitute for a view when the general use of a view is not required; that is, you do
not have to store the definition in metadata.
• Will be run when called, not when defined. If the CTE is used multiple times in a query it will
be run multiple times (possibly with different results).

Examples
Temporary query

These behave in the same manner as nested subqueries but with a different syntax.

WITH ReadyCars AS (
SELECT *

https://riptutorial.com/ 20
FROM Cars
WHERE Status = 'READY'
)
SELECT ID, Model, TotalCost
FROM ReadyCars
ORDER BY TotalCost;

ID Model TotalCost

1 Ford F-150 200

2 Ford F-150 230

Equivalent subquery syntax

SELECT ID, Model, TotalCost


FROM (
SELECT *
FROM Cars
WHERE Status = 'READY'
) AS ReadyCars
ORDER BY TotalCost

recursively going up in a tree

WITH RECURSIVE ManagersOfJonathon AS (


-- start with this row
SELECT *
FROM Employees
WHERE ID = 4

UNION ALL

-- get manager(s) of all previously selected rows


SELECT Employees.*
FROM Employees
JOIN ManagersOfJonathon
ON Employees.ID = ManagersOfJonathon.ManagerID
)
SELECT * FROM ManagersOfJonathon;

Id FName LName PhoneNumber ManagerId DepartmentId

4 Johnathon Smith 1212121212 2 1

2 John Johnson 2468101214 1 1

1 James Smith 1234567890 NULL 1

generating values

Most databases do not have a native way of generating a series of numbers for ad-hoc use;

https://riptutorial.com/ 21
however, common table expressions can be used with recursion to emulate that type of function.

The following example generates a common table expression called Numbers with a column i which
has a row for numbers 1-5:

--Give a table name `Numbers" and a column `i` to hold the numbers
WITH Numbers(i) AS (
--Starting number/index
SELECT 1
--Top-level UNION ALL operator required for recursion
UNION ALL
--Iteration expression:
SELECT i + 1
--Table expression we first declared used as source for recursion
FROM Numbers
--Clause to define the end of the recursion
WHERE i < 5
)
--Use the generated table expression like a regular table
SELECT i FROM Numbers;

This method can be used with any number interval, as well as other types of data.

recursively enumerating a subtree

WITH RECURSIVE ManagedByJames(Level, ID, FName, LName) AS (


-- start with this row
SELECT 1, ID, FName, LName
FROM Employees
WHERE ID = 1

UNION ALL

-- get employees that have any of the previously selected rows as manager
SELECT ManagedByJames.Level + 1,
Employees.ID,
Employees.FName,
Employees.LName
FROM Employees
JOIN ManagedByJames
ON Employees.ManagerID = ManagedByJames.ID

ORDER BY 1 DESC -- depth-first search

https://riptutorial.com/ 22

You might also like