我对此查询的执行顺序感到困惑,请解释一下.我很困惑何时应用连接,调用函数,随Case添加新列以及添加序列号时.请解释所有这些的执行顺序.
select Row_number() OVER(ORDER BY (SELECT 1)) AS 'Serial Number',
EP.FirstName,Ep.LastName,[dbo].[GetBookingRoleName](ES.UserId,EP.BookingRole) as RoleName,
(select top 1 convert(varchar(10),eventDate,103)from [3rdi_EventDates] where EventId=13) as EventDate,
(CASE [dbo].[GetBookingRoleName](ES.UserId,EP.BookingRole)
WHEN '90 Day Client' THEN 'DC'
WHEN 'Association Client' THEN 'DC'
WHEN 'Autism Whisperer' THEN 'DC'
WHEN 'CampII' THEN 'AD'
WHEN 'Captain' THEN 'AD'
WHEN 'Chiropractic Assistant' THEN 'AD'
WHEN 'Coaches' THEN 'AD'
END) as Category from [3rdi_EventParticipants] as EP
inner join [3rdi_EventSignup] as ES on EP.SignUpId = ES.SignUpId
where EP.EventId = 13
and userid in (
select distinct userid from userroles
--where roleid not in(6,7,61,64) and roleid not in(1,2))
where roleid not in(19, 20, 21, 22) and roleid not in(1,2))
Run Code Online (Sandbox Code Playgroud)
这是从上面的查询中调用的函数.
CREATE function [dbo].[GetBookingRoleName]
(
@UserId as integer,
@BookingId as integer
)
RETURNS varchar(20)
as
begin
declare @RoleName varchar(20)
if @BookingId = -1
Select Top 1 @RoleName=R.RoleName From UserRoles UR inner join Roles R on UR.RoleId=R.RoleId Where UR.UserId=@UserId and R.RoleId not in(1,2)
else
Select @RoleName= RoleName From Roles where RoleId = @BookingId
return @RoleName
end
Run Code Online (Sandbox Code Playgroud)
Rem*_*anu 46
SQL没有执行顺序.是一种声明性语言.优化器可以自由选择任何合适的顺序来产生最佳执行时间.给定任何SQL查询,基本上不可能任何人假装它知道执行顺序.如果您添加有关所涉及的模式的详细信息(确切的表和索引定义)和估计的基数(数据的大小和键的选择性),那么可以猜测可能的执行顺序.
最终,唯一正确的"顺序"是描述实际执行计划的顺序.请参阅使用SQL Server Profiler事件类显示执行计划并显示图形执行计划(SQL Server Management Studio).
但完全不同的是,查询,子查询和表达式如何将自己投射到"有效性"中.例如,如果SELECT投影列表中有别名表达式,是否可以在WHERE子句中使用别名?像这样:
SELECT a+b as c
FROM t
WHERE c=...;
Run Code Online (Sandbox Code Playgroud)
c在where子句中使用别名是否有效?答案是不.查询形成语法树,树的下部分支不能引用树中更高的定义.这不一定是"执行"的顺序,更多的是语法分析问题.它等同于在C#中编写此代码:
void Select (int a, int b)
{
if (c = ...) then {...}
int c = a+b;
}
Run Code Online (Sandbox Code Playgroud)
就像在C#中一样,这段代码不能编译,因为在c定义之前使用了变量,上面的SELECT将无法正确编译,因为别名c在树中的引用低于实际定义.
不幸的是,与众所周知的C/C#语言解析规则不同,构建查询树的SQL规则在某种程度上是深奥的.在单一SQL语句处理中简要提及它们,但详细讨论了它们是如何创建的,以及哪些顺序是有效的,哪些不是,我不知道任何来源.我不是说没有好的资料来源,我确信那里有一些好的SQL书籍涵盖了这个主题.
请注意,语法树顺序与SQL文本的可视顺序不匹配.例如,ORDER BY子句通常是SQL文本中的最后一个,但作为语法树,它位于其他所有内容之上(它对SELECT 的输出进行排序,因此它位于SELECTed列的上方),因此是有效引用c别名:
SELECT a+b as c
FROM t
ORDER BY c;
Run Code Online (Sandbox Code Playgroud)
更新
实际上有这样的:SELECT语句的逻辑处理顺序
以下步骤显示SELECT语句的逻辑处理顺序或绑定顺序.此顺序确定在一个步骤中定义的对象何时可用于后续步骤中的子句.例如,如果查询处理器可以绑定(访问)FROM子句中定义的表或视图,则这些对象及其列可供所有后续步骤使用.相反,因为SELECT子句是步骤8,所以前面的子句不能引用该子句中定义的任何列别名或派生列.但是,它们可以由后续子句引用,例如ORDER BY子句.请注意,语句的实际物理执行由查询处理器确定,并且顺序可能与此列表不同.
- 从
- 上
- 加入
- 哪里
- 通过...分组
- WITH CUBE或WITH ROLLUP
- HAVING
- 选择
- 不同
- 订购
- 最佳
Ran*_*der 43
查询通常按以下顺序处理(SQL Server).我不知道其他RDBMS是否这样做.
FROM [MyTable]
ON [MyCondition]
JOIN [MyJoinedTable]
WHERE [...]
GROUP BY [...]
HAVING [...]
SELECT [...]
ORDER BY [...]
Run Code Online (Sandbox Code Playgroud)
SQL是一种声明性语言,这意味着它告诉SQL引擎该做什么而不是该怎么做。这与命令式语言(例如C)形成了鲜明的对比,在命令式语言中明确列出了如何做某事。
这意味着并非所有语句都会按预期执行。需要特别注意的是布尔表达式,它们可能不会按照从左到右的顺序求值。例如,以下代码不能保证没有零除错误地执行:
SELECT 'null' WHERE 1 = 1 OR 1 / 0 = 0
Run Code Online (Sandbox Code Playgroud)
原因是查询优化器选择最佳(最有效)的方式执行语句。这意味着,例如,可能在应用转换谓词之前加载和过滤值,从而导致错误。有关示例,请参见上面的第二个链接
SQL 查询不是命令式的而是声明式的,因此您不知道先执行哪个语句,但是由于 SQL 是由 SQL 查询引擎评估的,因此大多数 SQL 引擎都遵循类似的过程来获取结果。您可能需要了解查询引擎在内部如何工作才能了解某些 SQL 执行行为。
Julia Evens 有一篇很好的文章解释了这一点,值得一看:
https://jvns.ca/blog/2019/10/03/sql-queries-don-t-start-with-select/