2011-01-04 40 views
12

Estoy confundido con el orden de ejecución de esta consulta, explíqueme esto. Se me confunde cuando se aplica la unión, se llama a la función, se agrega una nueva columna con la caja y cuando se agrega el número de serie. Por favor explique el orden de ejecución de todo esto.Orden de ejecución de la consulta SQL

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)) 

Esta es la función que se llama desde la consulta anterior.

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 [email protected] and R.RoleId not in(1,2) 
else 
Select @RoleName= RoleName From Roles where RoleId = @BookingId 

return @RoleName 
end 
+0

Fuera de tema, pero es probable que sea mucho mejor que la UDF zanjas y haciendo que la línea lógica. –

Respuesta

26

SQL no tiene ningún orden de ejecución. Es un lenguaje declarativo El optimizador es libre de elegir cualquier orden que se considere apropiada para producir el mejor tiempo de ejecución. Dada una consulta SQL, es básicamente imposible que alguien pretenda conocer el orden de ejecución. Si agrega información detallada sobre el esquema involucrado (tablas exactas y definición de índices) y las cardinalidades estimadas (tamaño de los datos y selectividad de las claves), entonces puede tomar una conjetura en el probable orden de ejecución.

En última instancia, la única 'orden' correcta es la que se describe en el plan de ejecución real. Ver Displaying Execution Plans by Using SQL Server Profiler Event Classes y Displaying Graphical Execution Plans (SQL Server Management Studio).

Sin embargo, una cosa completamente diferente es cómo las consultas, subconsultas y expresiones se proyectan en 'validez'. Por ejemplo, si tiene una expresión con alias en la lista de proyección SELECT, ¿puede usar el alias en la cláusula WHERE? De esta manera:

SELECT a+b as c 
FROM t 
WHERE c=...; 

es el uso de c alias válido en la cláusula where? La respuesta es no. Las consultas forman un árbol de sintaxis, y una rama inferior del árbol no puede ser referencia de algo definido más arriba en el árbol. Esto no es necesariamente un orden de 'ejecución', es más un problema de análisis de sintaxis. Es equivalente a escribir el código en C#:

void Select (int a, int b) 
{ 
    if (c = ...) then {...} 
    int c = a+b; 
} 

Al igual que en C# este código no se compilará porque la variable c se utiliza antes se define, la instrucción SELECT anterior no se compilará correctamente porque el alias c es referenciado más abajo en el árbol de lo que realmente está definido.

Desafortunadamente, a diferencia de las reglas bien conocidas del análisis sintáctico del lenguaje C/C#, las reglas SQL de cómo se construye el árbol de consulta son de alguna manera esotéricas. Hay una breve mención de ellos en Single SQL Statement Processing pero una discusión detallada de cómo se crean, y qué orden es válida y qué no, no sé de ninguna fuente. No estoy diciendo que no haya buenas fuentes, estoy seguro de que algunos de los buenos libros SQL que existen cubren este tema.

Tenga en cuenta que el orden del árbol de sintaxis no coincide con el orden visual del texto SQL.Por ejemplo, la cláusula ORDER BY suele ser la última en el texto SQL, pero como árbol de sintaxis se encuentra por encima de todo (ordena output de SELECT, por lo que se encuentra sobre las columnas SELECTed por así decirlo) y como tal es es válida para hacer referencia al c alias:

SELECT a+b as c 
FROM t 
ORDER BY c; 

Actualizado

en realidad no es lo siguiente: Logical Processing Order of the SELECT statement

The following steps show the logical processing order, or binding order, for a SELECT statement. This order determines when the objects defined in one step are made available to the clauses in subsequent steps. For example, if the query processor can bind to (access) the tables or views defined in the FROM clause, these objects and their columns are made available to all subsequent steps. Conversely, because the SELECT clause is step 8, any column aliases or derived columns defined in that clause cannot be referenced by preceding clauses. However, they can be referenced by subsequent clauses such as the ORDER BY clause. Note that the actual physical execution of the statement is determined by the query processor and the order may vary from this list.

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE or WITH ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP
+0

pero en mi consulta anterior cuando mi función se llama? después del resultado de fatching de join of before, si antes de eso, de dónde obtiene el valor del parámetro, también cuando se ejecuta "(seleccione la conversión top 1 (varchar (10), eventDate, 103) desde [3rdi_EventDates] donde EventId = 13) ", y cuando se ejecuta ese caso para una nueva columna – NoviceToDotNet

+0

La única manera de averiguarlo es mirar el plan de ejecución real. Hay –

+4

* * CAMINO demasiadas respuestas de todo el Internet/SO que dicen "optimizadores de SQL no es magia - nadie puede saber cómo una determinada consulta se ejecutará". ¡Pero cuando te das cuenta de que está más abajo, esto no es verdad! Sí, el optimizador hace cosas al azar, pero obviamente hay * algunas * órdenes de ejecución de cláusulas. O bien, ¿cómo podrías depender de una consulta? Por favor, mueva su actualización a la parte superior, por lo que las personas que están en busca de una respuesta no ven su respuesta equivocada en la parte superior y luego salen del hilo ... – mmcrae

24

Las consultas generalmente se procesan en el siguiente orden (SQL Server). No tengo idea si otros RDBMS lo hacen de esta manera.

FROM [MyTable] 
    ON [MyCondition] 
    JOIN [MyJoinedTable] 
WHERE [...] 
GROUP BY [...] 
HAVING [...] 
SELECT [...] 
ORDER BY [...] 
+2

esta es la respuesta correcta pero tiene tan pocos votos ... – mmcrae

+0

¡Estoy de acuerdo! Breve y dulce explicación. Mi voto positivo para esta respuesta. –

+0

Si la respuesta marcada como correcta engañar un poco –

2

"Orden de ejecución" es probablemente un mal modelo mental para las consultas SQL. Es difícil escribir una sola consulta que realmente dependería del orden de ejecución (esto es algo bueno). En su lugar debe pensar en todos se unen y donde cláusulas que suceden al mismo tiempo (casi como una plantilla)

Dicho esto podría ejecutar visualizar el Execution Plans que se debe dar una idea de ella.

Sin embargo, dado que no está claro por qué quieres saber el orden de ejecución, supongo que intentas obtener un modelo mental para esta consulta para que puedas arreglarlo de alguna manera. Así es como "traduciré" tu consulta, aunque he hecho bien con este tipo de análisis, hay un área gris con su precisión.

DE Y cláusula WHERE

  • Dame todas las filas de los participantes del evento. from [3rdi_EventParticipants

  • También me dan todas las filas Evento Registrar que responden a las filas de los participantes del evento en SignUpID inner join 3rdi_EventSignup] as ES on EP.SignUpId = ES.SignUpId

  • pero sólo por Evento 13 EP.EventId = 13

  • y sólo si el ID de usuario tiene un registro en la tabla de funciones de usuario donde el ID de función no está en 1,2,19,20,21,22 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))

SELECT CLA Uso

  • Para cada una de las filas dame un identificador único Row_number() OVER(ORDER BY (SELECT 1)) AS 'Serial Number',

  • Los participantes Nombre EP.FirstName

  • los participantes Apellido Ep.LastName

  • El nombre de Reservas Rol GetBookingRoleName

  • ir a buscar en las fechas de eventos y averiguar lo que el primer eventDate donde el EventId = 13 que se encuentran (select top 1 convert(varchar(10),eventDate,103)from [3rdi_EventDates] where EventId=13) as EventDate

  • En resumen, traducir la GetBookingRoleName en Categoría.No tengo una mesa para esto, así que voy mapa manualmente (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

Así que un par de notas aquí. No estás ordenando nada cuando seleccionas TOP. Probablemente deberías tener una orden por allí. También podría poner eso en su cláusula de.

from [3rdi_EventParticipants] as EP 
    inner join [3rdi_EventSignup] as ES on EP.SignUpId = ES.SignUpId, 
     (select top 1 convert(varchar(10),eventDate,103) 
     from [3rdi_EventDates] where EventId=13 
     Order by eventDate) dates 
3

SQL es un lenguaje declarativo, lo que significa que le dice al motor SQL qué hacer, no cómo. Esto está en contraste con un lenguaje imperativo como C, en el que la forma de hacer algo está claramente establecida.

Esto significa que no todas las declaraciones se ejecutará como se esperaba. De particular interés son las expresiones booleanas, que pueden no evaluarse de izquierda a derecha como están escritas. Por ejemplo, el siguiente código no está garantizada para ejecutar sin un error de división por cero:

SELECT 'null' WHERE 1 = 1 OR 1/0 = 0 

La razón de esto es que el optimizador de consultas elige la mejor manera (más eficiente) para ejecutar una instrucción. Esto significa que, por ejemplo, un valor puede cargarse y filtrarse antes de que se aplique un predicado de transformación, causando un error. Vea el segundo enlace de arriba para un ejemplo

Ver: here y here.

Cuestiones relacionadas