SQL查询的执行顺序

Nov*_*Net 27 sql-server

我对此查询的执行顺序感到困惑,请解释一下.我很困惑何时应用连接,调用函数,随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子句.请注意,语句的实际物理执行由查询处理器确定,并且顺序可能与此列表不同.

  1. 加入
  2. 哪里
  3. 通过...分组
  4. WITH CUBE或WITH ROLLUP
  5. HAVING
  6. 选择
  7. 不同
  8. 订购
  9. 最佳

  • 互联网上有*WAY*太多的答案/ SO说"SQL优化器是它的魔力 - 没有人能够知道给定的查询将如何执行".但是当你意识到更低时,这不是真的!是的,优化器会做随机的东西 - 但显然有一些*子句的执行顺序.或者,你怎么能依赖查询?请将您的更新移至顶部,以便正在寻找答案的人在顶部看不到您错误的答案,然后离开主题...... (9认同)

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)

  • @littleO这个答案描述了一种理解数据库可以做什么来执行查询的好方法;这作为**教学工具**很有用,因此新学生可以更轻松地理解 SQL。然而,SQL 是一种声明性语言,而不是像 C、Java、Python 等那样的命令式语言。这意味着现实世界中的生产数据库可以自由地重新措辞、重写查询、将其翻过来并以任何顺序执行。正如这个答案所解释的,只有一个简单的数据库才会执行查询;任何中高档数据库都会使用各种肮脏的技巧来使查询速度极快。 (2认同)

Iam*_*mIC 6

SQL是一种声明性语言,这意味着它告诉SQL引擎该做什么而不是该怎么做。这与命令式语言(例如C)形成了鲜明的对比,在命令式语言中明确列出了如何做某事。

这意味着并非所有语句都会按预期执行。需要特别注意的是布尔表达式,它们可能不会按照从左到右的顺序求值。例如,以下代码不能保证没有零除错误地执行:

SELECT 'null' WHERE 1 = 1 OR 1 / 0 = 0
Run Code Online (Sandbox Code Playgroud)

原因是查询优化器选择最佳(最有效)的方式执行语句。这意味着,例如,可能在应用转换谓词之前加载和过滤值,从而导致错误。有关示例,请参见上面的第二个链接

请参阅:这里这里


nyb*_*bon 6

SQL 查询不是命令式的而是声明式的,因此您不知道先执行哪个语句,但是由于 SQL 是由 SQL 查询引擎评估的,因此大多数 SQL 引擎都遵循类似的过程来获取结果。您可能需要了解查询引擎在内部如何工作才能了解某些 SQL 执行行为。

Julia Evens 有一篇很好的文章解释了这一点,值得一看:

https://jvns.ca/blog/2019/10/03/sql-queries-don-t-start-with-select/

在此处输入图片说明