sql 表表达式 - 视图,临时表,表变量,派生表,表值函数,公用表表达式(CTE)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql 表表达式 - 视图,临时表,表变量,派生表,表值函数,公用表表达式(CTE)相关的知识,希望对你有一定的参考价值。

/************************************
TABLE EXPRESSIONS
************************************/

/*
Table expressions are results sets that can be referenced and acted upon as it they are a table. Some have finite lifetimes or scopes. Examples are:

VIEWS - a saved, named query. When updating a view, you can only update one of the underlying tables referenced by that view.

TEMPORARY TABLES - preceded by # in the name, such as #TempTable. Created in tempdb and deleted automatically. Global temporary tables are created with a ## prefix. Session-specific temporary tables are created with a # prefix (you can continue using that temp table until you disconnect from the session).

TABLE VARIABLES - similar to temporary tables. Introduced because temporary tables can cause recompilations and don't necessarily use resources in the most efficient way. These are scoped to the batch and not to the session (it doesn't survive past the execution of the current batch of SQL code). Generally use on smaller data sets.

TABLE VALUED FUNCTIONS - named objects with definitions stored in a database. A function that returns a virtual table. May be thought of as Views that allow parameters.

DERIVED TABLES - a subquery within an outer SELECT statement that returns a multi-columned table. query expressions created within an outer SELECT statement. Not stored in the database - represents a virtual table. Scope of a derived table is the query in which it is defined (it doesn't exist outside of that specific query). They must:

COMMON TABLE EXPRESSIONS - named table expression defined in scope of query (it doesn't exist outside of that specific query). Similar to derived table, but you declare the inner table (the CTE) at the top, and then below that you SELECT from the results of the CTE. Unlike derived tables, CTEs support multiple references and supports recursion (an expression that calls itself to loop back on itself).
*/

/************************************
VIEWS
************************************/

-- VIEWS - a saved, named query. When updating a view, you can only update one of the underlying tables referenced by that view.
CREATE VIEW vCustomerAddress
AS
  SELECT C.CustomerID, Firstname, LastName, AddressLine1, City, StateProvince
  FROM customers1 c
  JOIN customersaddress ca
  ON c.customerID = ca.customerID
  JOIN Address a
  ON ca.addressID = a.addressID;

-- TEMPORARY TABLES - preceded by # in the name, such as #TempTable. Created in tempdb and deleted automatically. Global temporary tables are created with a ## prefix. Session-specific temporary tables are created with a # prefix (you can continue using that temp table until you disconnect from the session).
CREATE TABLE #temptable (
  ProductID INT,
  ProductName VARCHAR(50));

-- TABLE VARIABLES - similar to temporary tables. Introduced because temporary tables can cause recompilations and don't necessarily use resources in the most efficient way. These are scoped to the batch and not to the session (it doesn't survive past the execution of the current batch of SQL code). Generally used on smaller data sets.
DECLARE @varProducts AS TABLE (
  ProductID INT,
  ProductName VARCHAR(50));

...
SELECT * FROM @varProducts;

-- TABLE VALUED FUNCTIONS - named objects with definitions stored in a database. A function that returns a virtual table. May be thought of as Views that allow parameters.
CREATE FUNCTION udf_prod_customer_date_table_valued(@productID INT)
RETURNS TABLE
AS
RETURN 
(
  SELECT CustomerID, OrderDate
  FROM orders1
  WHERE ProductID = @productID
);

SELECT * FROM udf_prod_customer_date_table_valued(1);


/************************************
DERIVED TABLES
************************************/

/* DERIVED TABLES - a subquery within an outer SELECT statement that returns a multi-columned table. query expressions created within an outer SELECT statement. Not stored in the database - represents a virtual table. Scope of a derived table is the query in which it is defined (it doesn't exist outside of that specific query). They must:

- have an alias
- have unique names for all columns
- Not use an ORDER BY clause (without TOP or OFFSET/FETCH)
- Not be referred to multiple times in the same query
*/
SELECT Category, COUNT(ProductID) AS Products
FROM
-- derived table
	(SELECT p.ProductID, p.Name AS Product, C.Name AS Category
	FROM products AS p
	JOIN ProductCategory AS c
	ON p.ProductCategoryID = c.ProductCategoryID) AS ProdCats
GROUP BY Category
ORDER BY Category;

/************************************
COMMON TABLE EXPRESSIONS (CTEs)
************************************/

-- COMMON TABLE EXPRESSIONS - named table expression defined in scope of query (it doesn't exist outside of that specific query). Similar to derived table, but you declare the inner table at the top, and then below that you SELECT from the results of the CTE. Unlike derived tables, CTEs support multiple references and supports recursion (an expression that calls itself to loop back on itself).
WITH CTE_year (OrderYear, CustID)
AS
(
	SELECT Year(orderdate), custid
	FROM orders
)
SELECT OrderYear, COUNT(DISTINCT CustID) AS Cust_Count
FROM CTE_year
GROUP BY orderyear;

----------------------------
-- DETAIL OF CREATING CTE --
----------------------------

-- names the CTE, gives it two columns named OrderYear and CustID
WITH CTE_year (OrderYear, CustID)
-- AS defines the inner query at the start
AS
(
-- SELECTs two columns worth of information, will be placed in the columns of the CTE in order
	SELECT Year(orderdate), custid
	FROM orders
)
-- outer query SELECT, pulls from the results of the inner query, the FROM points not to a table but to the CTE
SELECT OrderYear, COUNT(DISTINCT CustID) AS Cust_Count
FROM CTE_year
GROUP BY orderyear;

-- CTE example with recursion:
WITH DirectReports (ManagerID, EmployeeID, Title, EmployeeLevel)
AS
(
	--anchor query, serves as the base query, at enter returns 1 which is the base number later used by the recursive query.
	SELECT ManagerID, EmployeeID, Title, 1 AS EmployeeLevel
	FROM dbo.MyEmployees
	WHERE ManagerID IS NULL
	UNION ALL
	--recursive query, since it references the CTE itself 
	SELECT e.ManagerID, e.EmployeeID, e.Title, EmployeeLevel + 1
	FROM dbo.MyEmployees AS e
	INNER JOIN DirectReports AS d
	ON e.ManagerID = d.EmployeeID
)
SELECT * FROM DirectReports 
--WHERE clause is a means to stop the loop at a certain point through the data set. In this instance, it's stopping the loop once EmployeeLevel 1, 2, and 3 people have been selected. EmployeeLevel 4 and higher will not be selected. If this clause is ommited, it'll continue looping through all levels (including 4 and beyond) until no data is returned in the recursive query and the termination check breaks the loop.
WHERE EmployeeLevel <=3
ORDER BY EmployeeLevel, ManagerID
--breaks the loop after three instances if it gets stuck in an infinite loop
OPTION (MAXRECURSION 3);

/**************************
TABLE EXPRESSIONS VS. TEMPORARY TABLE VS. TABLE VARIABLE PERFORMANCE
***************************/

/*
There are cases where a table expression is more optimal than a temporary table. This is the case
when you need to query the results only once - it doesn't make sense to waste the resources to persist
the results to a table when you're only using it once.

Temporary tables often have better performance when you have a starting table result that you need
to access repeated times, especially if it's a large or expensive result. If you use a derived 
table and reference it multiple times in the outer query, the work is repeated each time. Therefore,
if you have an expensive inner query, it's best to instead persist this result to a temporary table, 
and then reference the temporary table as many times as you need. Each time you reference the 
temporary table, you will not be regenerating the result each time as you would be if you 
used a dereived table.

The difference between a temporary table and a table variable is that SQL SERVER maintains full 
statistics on temporary tables, but does not on table variables. Therefore, cardinality 
estimates (estimates for row counts) tend to be more accurate with temporary tables. Therfore the
recommendation is that with small amounts of data with just a few rows, use table variables. With 
larger tables sizes, the recommendation is to use temporary tables.
*/

以上是关于sql 表表达式 - 视图,临时表,表变量,派生表,表值函数,公用表表达式(CTE)的主要内容,如果未能解决你的问题,请参考以下文章

sql 视图,临时表,CTE,派生表

Hive 公用表表达式 CTE 使用指南

EXPLAIN sql优化方法DERIVED

sql server中的临时表表变量和公用表表达式

sqlserver 创建视图失败,原因:ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效

SQL Server 公用表表达式(CTE)实现递归