ima*_*mak 219 sql t-sql sql-server common-table-expression
我已经开始阅读有关Common Table Expression的内容,并且无法想到我需要使用它们的用例.它们似乎是多余的,因为派生表可以做到这一点.有什么我缺少或不理解?有人能给我一个简单的限制例子,通过常规的select,derived或temp表查询来说明CTE的情况吗?任何简单的例子都将受到高度赞赏.
Joh*_*som 190
例如,如果需要多次引用/连接相同的数据集,则可以通过定义CTE来实现.因此,它可以是一种代码重用的形式.
自引用的一个示例是递归:使用CTE的递归查询
CTE可用于:
创建递归查询.有关更多信息,请参阅使用公用表表达式的递归查询.
在不需要一般使用视图时替换视图; 也就是说,您不必将定义存储在元数据中.
通过从标量子选择派生的列或不具有确定性或具有外部访问权限的函数启用分组.
在同一语句中多次引用结果表.
n8w*_*wrl 47
我使用它们来分解复杂的查询,尤其是复杂的连接和子查询.我发现我越来越多地使用它们作为"伪视图"来帮助我了解查询的意图.
我对他们的唯一抱怨是他们无法重复使用.例如,我可能有一个存储过程,其中包含两个可以使用相同CTE的更新语句.但CTE的"范围"仅是第一个查询.
麻烦的是,"简单的例子"可能并不真正需要CTE!
还是,非常方便.
Bri*_*anK 42
我看到使用cte的原因有两个.
在where子句中使用计算值.这对我来说似乎比派生表更清洁.
假设有两个表 - 问题和答案由Questions.ID = Answers.Question_Id(和测验ID)连接在一起
WITH CTE AS
(
Select Question_Text,
(SELECT Count(*) FROM Answers A WHERE A.Question_ID = Q.ID) AS Number_Of_Answers
FROM Questions Q
)
SELECT * FROM CTE
WHERE Number_Of_Answers > 0
Run Code Online (Sandbox Code Playgroud)
这是另一个我希望获得问题和答案列表的例子.我希望将答案与结果中的问题分组.
WITH cte AS
(
SELECT [Quiz_ID]
,[ID] AS Question_Id
,null AS Answer_Id
,[Question_Text]
,null AS Answer
,1 AS Is_Question
FROM [Questions]
UNION ALL
SELECT Q.[Quiz_ID]
,[Question_ID]
,A.[ID] AS Answer_Id
,Q.Question_Text
,[Answer]
,0 AS Is_Question
FROM [Answers] A INNER JOIN [Questions] Q ON Q.Quiz_ID = A.Quiz_ID AND Q.Id = A.Question_Id
)
SELECT
Quiz_Id,
Question_Id,
Is_Question,
(CASE WHEN Answer IS NULL THEN Question_Text ELSE Answer END) as Name
FROM cte
GROUP BY Quiz_Id, Question_Id, Answer_id, Question_Text, Answer, Is_Question
order by Quiz_Id, Question_Id, Is_Question Desc, Name
Run Code Online (Sandbox Code Playgroud)
The*_*Man 20
我发现使用CTE有用的一个场景是当你想要根据一个或多个列获取DISTINCT数据行但返回表中的所有列时.使用标准查询,您可能首先必须将不同的值转储到临时表中,然后尝试将它们连接回原始表以检索其余列,或者您可以编写一个极其复杂的分区查询,该查询可以返回结果一次运行,但最有可能,它将是不可读的并导致性能问题.
但是通过使用CTE(由Tim Schmelter回答选择记录的第一个实例)
WITH CTE AS(
SELECT myTable.*
, RN = ROW_NUMBER()OVER(PARTITION BY patientID ORDER BY ID)
FROM myTable
)
SELECT * FROM CTE
WHERE RN = 1
Run Code Online (Sandbox Code Playgroud)
如您所见,这更容易阅读和维护.与其他查询相比,性能要好得多.
Vic*_*Vic 15
将CTE视为用于单个查询的视图的替代可能更有意义.但是不需要正式视图的开销,元数据或持久性.当您需要时非常有用:
这是一个可以使用的剪切和粘贴示例:
WITH [cte_example] AS (
SELECT 1 AS [myNum], 'a num' as [label]
UNION ALL
SELECT [myNum]+1,[label]
FROM [cte_example]
WHERE [myNum] <= 10
)
SELECT * FROM [cte_example]
UNION
SELECT SUM([myNum]), 'sum_all' FROM [cte_example]
UNION
SELECT SUM([myNum]), 'sum_odd' FROM [cte_example] WHERE [myNum] % 2 = 1
UNION
SELECT SUM([myNum]), 'sum_even' FROM [cte_example] WHERE [myNum] % 2 = 0;
Run Code Online (Sandbox Code Playgroud)
请享用
当您想要执行“有序更新”时,它非常有用。
MS SQL 不允许您将 ORDER BY 与 UPDATE 一起使用,但在 CTE 的帮助下,您可以这样做:
WITH cte AS
(
SELECT TOP(5000) message_compressed, message, exception_compressed, exception
FROM logs
WHERE Id >= 5519694
ORDER BY Id
)
UPDATE cte
SET message_compressed = COMPRESS(message), exception_compressed = COMPRESS(exception)
Run Code Online (Sandbox Code Playgroud)
在这里查看更多信息:How to update and order by using ms sql
今天我们将了解Common表表达式,它是SQL Server 2005中引入的新功能,也可以在更高版本中使用.
公用表表达式: - 公用表表达式可以定义为临时结果集,换句话说,它可以替代SQL Server中的视图.公用表表达式仅在定义它的批处理语句中有效,不能在其他会话中使用.
声明CTE的语法(公用表表达式): -
with [Name of CTE]
as
(
Body of common table expression
)
Run Code Online (Sandbox Code Playgroud)
让我们举一个例子: -
CREATE TABLE Employee([EID] [int] IDENTITY(10,5) NOT NULL,[Name] [varchar](50) NULL)
insert into Employee(Name) values('Neeraj')
insert into Employee(Name) values('dheeraj')
insert into Employee(Name) values('shayam')
insert into Employee(Name) values('vikas')
insert into Employee(Name) values('raj')
CREATE TABLE DEPT(EID INT,DEPTNAME VARCHAR(100))
insert into dept values(10,'IT')
insert into dept values(15,'Finance')
insert into dept values(20,'Admin')
insert into dept values(25,'HR')
insert into dept values(10,'Payroll')
Run Code Online (Sandbox Code Playgroud)
我创建了两个表employee和Dept,并在每个表中插入了5行.现在我想加入这些表并创建一个临时结果集以进一步使用它.
With CTE_Example(EID,Name,DeptName)
as
(
select Employee.EID,Name,DeptName from Employee
inner join DEPT on Employee.EID =DEPT.EID
)
select * from CTE_Example
Run Code Online (Sandbox Code Playgroud)
让我们逐一采用声明的每一行并理解.
要定义CTE,我们编写"with"子句,然后我们给表表达式命名,这里我给出了名称为"CTE_Example"的名称
然后我们写"As"并将我们的代码括在两个括号(---)中,我们可以在封闭的括号中连接多个表.
在最后一行中,我使用了"Select*from CTE_Example",我们在最后一行代码中引用Common表达式,所以我们可以说它就像一个视图,我们在一个视图中定义和使用视图batch和CTE不作为永久对象存储在数据库中.但它的行为就像一个观点.我们可以在CTE上执行删除和更新语句,这将对CTE中使用的引用表产生直接影响.让我们举个例子来理解这个事实.
With CTE_Example(EID,DeptName)
as
(
select EID,DeptName from DEPT
)
delete from CTE_Example where EID=10 and DeptName ='Payroll'
Run Code Online (Sandbox Code Playgroud)
在上面的语句中,我们从CTE_Example中删除一行,它将从CTE中使用的引用表"DEPT"中删除数据.