none
subconsultas RRS feed

  • Pregunta

  • Buenas tardes, tengo una duda sobre como debería ser la mejor manera de hacer una subconsulta, necesito obtener un Id  del mayor de dos campos para obtener el idCertificacion mayor (este id no es numérico), yo lo tengo con una subconsulta y el id que traiga de esa lo relaciono en la primera consulta, así:

    select idEstudiante, nombreEstudiante, idCertificacion

    from estudiante inner join certificacion on estudiante.idEstudiante= certificacion.idEstudiante

    inner join ( select idCertificacion, Max(fechanicio), Max(fechaFin) from 

    estudiante inner join certificacion on estudiante.idEstudiante= certificacion.idEstudiante

    group by idCertificacion

    ) as datos  ON datos.idCertificacion = certificacion.idCertificacion 

    Pero me gustaría si hay alguna forma de mejorarlo, o si es así la forma correcta, ya que me preocupa que con muchos registros se puede volver muy lento.

    Gracias.

    martes, 29 de diciembre de 2020 18:35

Todas las respuestas

  • Hola Ema08:

    TSQL es un lenguaje declarativo, que implica que no sabemos como va a ejecutar nuestra consulta el motor. El analizará la misma, y hará un plan de ejecución que considere óptimo, por los datos que tiene cada una de las tablas (o los que considera por sus estadísticas), por los índices existentes, por el número de tablas, por la posibilidad de crear tablas hash por la cantidad de datos.....y un largo etc, que evalúa al llegarle la consulta.

    Aunque tú consulta diga que hace no se que. Es bastante probable, que viendo la misma, no sea para nada parecido a lo que hace.

    Puedes ver el plan de ejecución en vivo desde el Sql Server Management studio.

    Una opción bastante simple, y que probablemente mejore tú rendimiento, es utilizar funciones para obtener el máximo.

    Drop Table If Exists estudiante;
    
    Drop Table If Exists certificacion;
    
    Create Table estudiante
    			 (
    			 idestudiante     Int
    		   , nombreestudiante VarChar(19)
    			 );
    
    Create Table certificacion
    			 (
    			 idcertificacion VarChar(10)
    		   , idestudiante    Int
    		   , fechainicio     DateTime2
    		   , fechafin        DateTime2
    			 );
    Go

    Insertamos datos.

    Insert into estudiante (idestudiante, nombreestudiante)
    values
    (1,'juan'),
    (2,'Ana');
    go
    Insert into certificacion (idcertificacion, idestudiante, fechainicio, fechafin)
    values 
    ('a',1,'20200101','20200201'),
    ('b',2,'20200101','20200201'),
    ('c',1,'20200201','20200301'),
    ('d',2,'20200201','20200301');
    go

    Ahora creamos una función tipo tabla que nos devolverá la mayor certificación para el estudiante pasado como parámetro.

    Create or alter function dbo.MaxCertificacion (@idestudiante int)
    returns table
    As
    Return
    		Select top(1) idcertificacion
    				From 
    						  certificacion 
    				where idestudiante = @idestudiante 
    					order by fechainicio desc, fechafin desc	
    		
    
    go

    De momento, ya le hemos quitado la tabla de estudiantes, y además no necesitamos agrupar.

    Ahora la consulta quedaría solo utilizando la tabla de estudiantes.

    Select estudiante.idestudiante
    	 , nombreestudiante
    	 , idcertificacion
    	   From estudiante
    			Cross Apply dbo.maxcertificacion
    			( estudiante.idestudiante ) As fn;

    La función nos retorna el máximo, del estudiante que le pasamos como parámetro.

    Operador apply

    https://javifer2.wordpress.com/2020/06/27/operador-apply/

    miércoles, 30 de diciembre de 2020 5:17