FROM (Transact-SQL)
Specifies the tables, views, derived tables, and joined tables used in DELETE, SELECT, and UPDATE statements in SQL Server 2012. In the SELECT statement, the FROM clause is required except when the select list contains only constants, variables, and arithmetic expressions (no column names).
[ FROM { <table_source> } [ ,...n ] ]
<table_source> ::=
{
table_or_view_name [ [ AS ] table_alias ] [ <tablesample_clause> ]
[ WITH ( < table_hint > [ [ , ]...n ] ) ]
| rowset_function [ [ AS ] table_alias ]
[ ( bulk_column_alias [ ,...n ] ) ]
| user_defined_function [ [ AS ] table_alias ] ]
| OPENXML <openxml_clause>
| derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ]
| <joined_table>
| <pivoted_table>
| <unpivoted_table>
| @variable [ [ AS ] table_alias ]
| @variable.function_call ( expression [ ,...n ] ) [ [ AS ] table_alias ] [ (column_alias [ ,...n ] ) ]
}
<tablesample_clause> ::=
TABLESAMPLE [SYSTEM] ( sample_number [ PERCENT | ROWS ] )
[ REPEATABLE ( repeat_seed ) ]
<joined_table> ::=
{
<table_source> <join_type> <table_source> ON <search_condition>
| <table_source> CROSS JOIN <table_source>
| left_table_source { CROSS | OUTER } APPLY right_table_source
| [ ( ] <joined_table> [ ) ]
}
<join_type> ::=
[ { INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } } [ <join_hint> ] ]
JOIN
<pivoted_table> ::=
table_source PIVOT <pivot_clause> [ AS ] table_alias
<pivot_clause> ::=
( aggregate_function ( value_column [ [ , ]...n ])
FOR pivot_column
IN ( <column_list> )
)
<unpivoted_table> ::=
table_source UNPIVOT <unpivot_clause> [ AS ] table_alias
<unpivot_clause> ::=
( value_column FOR pivot_column IN ( <column_list> ) )
<column_list> ::=
column_name [ ,...n ]
The FROM clause supports the SQL-92-SQL syntax for joined tables and derived tables. SQL-92 syntax provides the INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER, and CROSS join operators.
UNION and JOIN within a FROM clause are supported within views and in derived tables and subqueries.
A self-join is a table that is joined to itself. Insert or update operations that are based on a self-join follow the order in the FROM clause.
Because SQL Server considers distribution and cardinality statistics from linked servers that provide column distribution statistics, the REMOTE join hint is not required to force evaluating a join remotely. The SQL Server query processor considers remote statistics and determines whether a remote-join strategy is appropriate. REMOTE join hint is useful for providers that do not provide column distribution statistics.
Using APPLY
Both the left and right operands of the APPLY operator are table expressions. The main difference between these operands is that the right_table_source can use a table-valued function that takes a column from the left_table_source as one of the arguments of the function. The left_table_source can include table-valued functions, but it cannot contain arguments that are columns from the right_table_source.
The APPLY operator works in the following way to produce the table source for the FROM clause:
-
Evaluates right_table_source against each row of the left_table_source to produce rowsets.
The values in the right_table_source depend on left_table_source. right_table_source can be represented approximately this way: TVF(left_table_source.row), where TVF is a table-valued function.
-
Combines the result sets that are produced for each row in the evaluation of right_table_source with the left_table_source by performing a UNION ALL operation.
The list of columns produced by the result of the APPLY operator is the set of columns from the left_table_source that is combined with the list of columns from the right_table_source.
Using PIVOT and UNPIVOT
The pivot_column and value_column are grouping columns that are used by the PIVOT operator. PIVOT follows the following process to obtain the output result set:
-
Performs a GROUP BY on its input_table against the grouping columns and produces one output row for each group.
The grouping columns in the output row obtain the corresponding column values for that group in the input_table.
-
Generates values for the columns in the column list for each output row by performing the following:
-
Grouping additionally the rows generated in the GROUP BY in the previous step against the pivot_column.
For each output column in the column_list, selecting a subgroup that satisfies the condition:
pivot_column = CONVERT(<data type of pivot_column>, 'output_column')
-
aggregate_function is evaluated against the value_column on this subgroup and its result is returned as the value of the corresponding output_column. If the subgroup is empty, SQL Server generates a null value for that output_column. If the aggregate function is COUNT and the subgroup is empty, zero (0) is returned.
-
A. Using a simple FROM clause
The following example retrieves the TerritoryID and Name columns from the SalesTerritory table in the AdventureWorks2012 sample database.
USE AdventureWorks2012 ; GO SELECT TerritoryID, Name FROM Sales.SalesTerritory ORDER BY TerritoryID ;
Here is the result set.
TerritoryID Name ----------- ------------------------------ 1 Northwest 2 Northeast 3 Central 4 Southwest 5 Southeast 6 Canada 7 France 8 Germany 9 Australia 10 United Kingdom (10 row(s) affected)
B. Using the TABLOCK and HOLDLOCK optimizer hints
The following partial transaction shows how to place an explicit shared table lock on Employee and how to read the index. The lock is held throughout the whole transaction.
USE AdventureWorks2012 ; GO BEGIN TRAN SELECT COUNT(*) FROM HumanResources.Employee WITH (TABLOCK, HOLDLOCK) ;
C. Using the SQL-92 CROSS JOIN syntax
The following example returns the cross product of the two tables Employee and Department. A list of all possible combinations of BusinessEntityID rows and all Department name rows are returned.
USE AdventureWorks2012 ; GO SELECT e.BusinessEntityID, d.Name AS Department FROM HumanResources.Employee AS e CROSS JOIN HumanResources.Department AS d ORDER BY e.BusinessEntityID, d.Name ;
D. Using the SQL-92 FULL OUTER JOIN syntax
The following example returns the product name and any corresponding sales orders in the SalesOrderDetail table. It also returns any sales orders that have no product listed in the Product table, and any products with a sales order other than the one listed in the Product table.
USE AdventureWorks2012 ; GO -- The OUTER keyword following the FULL keyword is optional. SELECT p.Name, sod.SalesOrderID FROM Production.Product AS p FULL OUTER JOIN Sales.SalesOrderDetail AS sod ON p.ProductID = sod.ProductID WHERE p.ProductID IS NULL OR sod.ProductID IS NULL ORDER BY p.Name ;
E. Using the SQL-92 LEFT OUTER JOIN syntax
The following example joins two tables on ProductID and preserves the unmatched rows from the left table. The Product table is matched with the SalesOrderDetail table on the ProductID columns in each table. All products, ordered and not ordered, appear in the result set.
USE AdventureWorks2012 ; GO SELECT p.Name, sod.SalesOrderID FROM Production.Product AS p LEFT OUTER JOIN Sales.SalesOrderDetail AS sod ON p.ProductID = sod.ProductID ORDER BY p.Name ;
F. Using the SQL-92 INNER JOIN syntax
The following example returns all product names and sales order IDs.
USE AdventureWorks2012 ; GO -- By default, SQL Server performs an INNER JOIN if only the JOIN -- keyword is specified. SELECT p.Name, sod.SalesOrderID FROM Production.Product AS p INNER JOIN Sales.SalesOrderDetail AS sod ON p.ProductID = sod.ProductID ORDER BY p.Name ;
G. Using the SQL-92 RIGHT OUTER JOIN syntax
The following example joins two tables on TerritoryID and preserves the unmatched rows from the right table. The SalesTerritory table is matched with the SalesPerson table on the TerritoryID column in each table. All salespersons appear in the result set, whether or not they are assigned a territory.
USE AdventureWorks2012 ; GO SELECT st.Name AS Territory, sp.BusinessEntityID FROM Sales.SalesTerritory AS st RIGHT OUTER JOIN Sales.SalesPerson AS sp ON st.TerritoryID = sp.TerritoryID ;
H. Using HASH and MERGE join hints
The following example performs a three-table join among the Product, ProductVendor, and Vendor tables to produce a list of products and their vendors. The query optimizer joins Product and ProductVendor (p and pv) by using a MERGE join. Next, the results of the Product and ProductVendor MERGE join (p and pv) are HASH joined to the Vendor table to produce (p and pv) and v.
Important
|
|---|
|
After a join hint is specified, the INNER keyword is no longer optional and must be explicitly stated for an INNER JOIN to be performed. |
USE AdventureWorks2012 ; GO SELECT p.Name AS ProductName, v.Name AS VendorName FROM Production.Product AS p INNER MERGE JOIN Purchasing.ProductVendor AS pv ON p.ProductID = pv.ProductID INNER HASH JOIN Purchasing.Vendor AS v ON pv.BusinessEntityID = v.BusinessEntityID ORDER BY p.Name, v.Name ;
I. Using a derived table
The following example uses a derived table, a SELECT statement after the FROM clause, to return the first and last names of all employees and the cities in which they live.
USE AdventureWorks2012 ;
GO
SELECT RTRIM(p.FirstName) + ' ' + LTRIM(p.LastName) AS Name, d.City
FROM Person.Person AS p
INNER JOIN HumanResources.Employee e ON p.BusinessEntityID = e.BusinessEntityID
INNER JOIN
(SELECT bea.BusinessEntityID, a.City
FROM Person.Address AS a
INNER JOIN Person.BusinessEntityAddress AS bea
ON a.AddressID = bea.AddressID) AS d
ON p.BusinessEntityID = d.BusinessEntityID
ORDER BY p.LastName, p.FirstName;
J. Using TABLESAMPLE to read data from a sample of rows in a table
The following example uses TABLESAMPLE in the FROM clause to return approximately 10 percent of all the rows in the Customer table.
USE AdventureWorks2012 ; GO SELECT * FROM Sales.Customer TABLESAMPLE SYSTEM (10 PERCENT) ;
K. Using APPLY
The following example assumes that the following tables with the following schema exist in the database:
-
Departments: DeptID, DivisionID, DeptName, DeptMgrID
-
EmpMgr: MgrID, EmpID
-
Employees: EmpID, EmpLastName, EmpFirstName, EmpSalary
There is also a table-valued function, GetReports(MgrID) that returns the list of all employees (EmpID, EmpLastName, EmpSalary) that report directly or indirectly to the specified MgrID.
The example uses APPLY to return all departments and all employees in that department. If a particular department does not have any employees, there will not be any rows returned for that department.
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary FROM Departments d CROSS APPLY dbo.GetReports(d.DeptMgrID) ;
If you want the query to produce rows for those departments without employees, which will produce null values for the EmpID, EmpLastName and EmpSalary columns, use OUTER APPLY instead.
SELECT DeptID, DeptName, DeptMgrID, EmpID, EmpLastName, EmpSalary FROM Departments d OUTER APPLY dbo.GetReports(d.DeptMgrID) ;
L. Using PIVOT and UNPIVOT
The following example returns the number of purchase orders placed by employee IDs 164, 198, 223, 231, and 233, categorized by vendor ID.
USE AdventureWorks2012; GO SELECT VendorID, [250] AS Emp1, [251] AS Emp2, [256] AS Emp3, [257] AS Emp4, [260] AS Emp5 FROM (SELECT PurchaseOrderID, EmployeeID, VendorID FROM Purchasing.PurchaseOrderHeader) AS p PIVOT ( COUNT (PurchaseOrderID) FOR EmployeeID IN ( [250], [251], [256], [257], [260] ) ) AS pvt ORDER BY VendorID;
Here is a partial result set:
VendorID Emp1 Emp2 Emp3 Emp4 Emp5
----------------------------------------------------------------
1 4 3 5 4 4
2 4 1 5 5 5
3 4 3 5 4 4
4 4 2 5 5 4
5 5 1 5 5 5
To unpivot the table, assume the result set produced in the previous example is stored as pvt. The query looks like the following.
--Create the table and insert values as portrayed in the previous example.
CREATE TABLE dbo.pvt (VendorID int, Emp1 int, Emp2 int,
Emp3 int, Emp4 int, Emp5 int);
GO
INSERT INTO dbo.pvt VALUES
(1,4,3,5,4,4)
,(2,4,1,5,5,5)
,(3,4,3,5,4,4)
,(4,4,2,5,5,4)
,(5,5,1,5,5,5);
GO
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM dbo.pvt) AS p
UNPIVOT
(Orders FOR Employee IN
(Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt
GO
Here is a partial result set:
VendorID Employee Orders
------------------------------
1 Emp1 4
1 Emp2 3
1 Emp3 5
1 Emp4 4
1 Emp5 4
2 Emp1 4
2 Emp2 1
2 Emp3 5
2 Emp4 5
2 Emp5 5
M. Using CROSS APPLY
The following example retrieves a snapshot of all query plans residing in the plan cache, by querying the sys.dm_exec_cached_plans dynamic management view to retrieve the plan handles of all query plans in the cache. Then the CROSS APPLY operator is specified to pass the plan handles to sys.dm_exec_query_plan. The XML Showplan output for each plan currently in the plan cache is in the query_plan column of the table that is returned.
USE master; GO SELECT dbid, object_id, query_plan FROM sys.dm_exec_cached_plans AS cp CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle); GO