none
COMO OPTIMIZAR ESTE QUERY RRS feed

  • Pregunta

  • COMO OPTIMIZAR ESTE QUERY

    SELECT 
    'CUOTA' AS 'TIPO MOV.', No AS 'NO. DOC', Fechas AS FECHA,'CUOTA  # ' + CAST(NO AS NVARCHAR(10))
      + '/' + CAST((SELECT COUNT(NO) FROM TbCuota WHERE Id_Prestamo = 1 AND Id_Compania = 1) AS NVARCHAR(10)) AS CONCEPTO
    , Capital + Interes AS VALOR, Mora AS MORA FROM TbCuota WHERE Id_Prestamo = 1 AND Id_Compania = 1
      UNION
    SELECT 
    'PAGO' AS 'TIPO MOV.', Id_Cobro AS 'NO. DOC', Fecha_Cobro AS FECHA, Descripcion AS CONCEPTO, 
     Capital + Interes AS VALOR, Mora AS MORA FROM TbCOBRO WHERE Id_Prestamo = 1 AND Id_Compania = 1
      UNION
     SELECT 
     'NC' AS 'TIPO MOV.', Id_Doc AS 'NO. DOC', Fecha AS FECHA, Concepto AS CONCEPTO
     ,Capital + Interes AS VALOR, Mora AS MORA FROM TbNotas WHERE Id_Prestamo = 1 AND Id_Compania = 1 AND DOC = 'NC'
      UNION
     SELECT 
     'ND' AS 'TIPO MOV.', Id_Doc AS 'NO. DOC', Fecha AS FECHA, Concepto AS CONCEPTO
     ,Capital + Interes AS VALOR, Mora AS MORA FROM TbNotas WHERE Id_Prestamo = 1 AND Id_Compania = 1 AND DOC = 'ND'

    miércoles, 10 de diciembre de 2014 20:59

Respuestas

  • Hola,

    No hay mucho que hacer, sólo en las dos últimas consultas ambas salen de la misma tabla y sólo se diferencia por el tipo de documento. 

    Te dejo el código mejorado

    SELECT 
    	'CUOTA' AS 'TIPO MOV.', 
    	No AS 'NO. DOC', 
    	Fechas AS FECHA,
    	'CUOTA  # ' + CAST(NO AS NVARCHAR(10))  + '/' + CAST((SELECT COUNT(NO) FROM TbCuota WHERE Id_Prestamo = 1 AND Id_Compania = 1) AS NVARCHAR(10)) AS CONCEPTO, 
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbCuota 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1
    
    UNION ALL
    
    SELECT 
    	'PAGO' AS 'TIPO MOV.', 
    	Id_Cobro AS 'NO. DOC', 
    	Fecha_Cobro AS FECHA, 
    	Descripcion AS CONCEPTO, 
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbCOBRO 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1
    
    UNION ALL
    
    SELECT 
    	DOC AS 'TIPO MOV.', 
    	Id_Doc AS 'NO. DOC', 
    	Fecha AS FECHA, 
    	Concepto AS CONCEPTO,
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbNotas 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1

    PERO, veo ahí dos problemas. Primero, se entiende que este informe es para presentar los pagos realizados respecto a las deudas y además las NC y ND que han venido presentándose en el transcurso de la operación. Si lo haces tal cuál no tendrá un orden cronológico de los sucesos. Segundo, revisa la subconsulta para obtener el nro de cuota, siempre te saldrá el mismo nro.

    Te sugiero esto que incluso creo será más rápido

    DECLARE @Temporal table (idTemp int IDENTITY(1,1), tipomov nvarchar(100), numdoc nvarchar(100), fecha datetime, concepto nvarchar(100), valor decimal(19,5), mora decimal(19,5));
    
    /*INSERTAS TODOS LOS DATOS EN UNA TABLA TEMPORAL*/
    
    INSERT INTO @Temporal (tipomov, numdoc, fecha, concepto, valor, mora)
    SELECT 
    	'CUOTA' AS 'TIPO MOV.', 
    	No AS 'NO. DOC', 
    	Fechas AS FECHA,
    	'' AS CONCEPTO, 
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbCuota 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1;
    
    INSERT INTO @Temporal (tipomov, numdoc, fecha, concepto, valor, mora)
    SELECT 
    	'PAGO' AS 'TIPO MOV.', 
    	Id_Cobro AS 'NO. DOC', 
    	Fecha_Cobro AS FECHA, 
    	Descripcion AS CONCEPTO, 
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbCOBRO 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1;
    
    INSERT INTO @Temporal (tipomov, numdoc, fecha, concepto, valor, mora)
    SELECT 
    	DOC AS 'TIPO MOV.', 
    	Id_Doc AS 'NO. DOC', 
    	Fecha AS FECHA, 
    	Concepto AS CONCEPTO,
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbNotas 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1;
    
    /*MUESTRAS LA TABLA TEMPORAL EN EL ORDEN CRONOLOGICO DE LAS OPERACIONES*/
    SELECT
    	tipomov, 
    	numdoc, 
    	fecha, 
    	CASE
    		WHEN tipomov = 'CUOTA' THEN idTemp /*Con esto devuelves el nro de cuota correlativo*/
    		ELSE concepto
    	END, 
    	valor, 
    	mora
    FROM
    	@Temporal
    ORDER BY
    	fecha;

    Salvo error u omisión esto estará OK

    Espero haberte ayudado con mi respuesta, si te fue útil no olvides marcarla como correcta.







    miércoles, 10 de diciembre de 2014 21:08
  • Lo primero seria cambiar todos los operadores UNION por UNION ALL ya que los cuatro conjuntos son mutuamente excluyentes.

    SELECT 'CUOTA' AS [TIPO MOV.]
    UNION
    SELECT 'PAGO' AS [TIPO MOV.]
    UNION
    SELECT 'NC' AS [TIPO MOV.]
    UNION
    SELECT 'ND' AS [TIPO MOV.];
    
    SELECT 'CUOTA' AS [TIPO MOV.]
    UNION ALL
    SELECT 'PAGO' AS [TIPO MOV.]
    UNION ALL
    SELECT 'NC' AS [TIPO MOV.]
    UNION ALL
    SELECT 'ND' AS [TIPO MOV.];

    Si chequeas el plan de ejecucion de tu query, notaras operadores de ordenacion (sort iterator) lo cual se usa para poder eliminar duplicados que es lo que tratas de hacer con UNION.

    Te recomiendo que uses los corchetes cuadrados ([]) o doble comilla (") para delimitar identificadores. Esto no tiene implicacion en el desempenio pero hara tu codigo mas legible.

    Las ultimas dos sentencias puedes reemplazarlas por una sola.

    SELECT
        'CUOTA' AS [TIPO MOV.],
        No AS [NO. DOC],
        Fechas AS FECHA,
        'CUOTA  # ' + CAST(NO AS nvarchar(10)) + '/'
        + CAST((
                SELECT
                    COUNT(NO)
                FROM
                    TbCuota
                WHERE
                    Id_Prestamo = 1
                    AND Id_Compania = 1
               ) AS nvarchar(10)) AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbCuota
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
        
    UNION ALL
    
    SELECT
        'PAGO' AS [TIPO MOV.],
        Id_Cobro AS [NO. DOC],
        Fecha_Cobro AS FECHA,
        Descripcion AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbCOBRO
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
    
    UNION ALL
    
    SELECT
        DOC AS [TIPO MOV.],
        Id_Doc AS [NO. DOC],
        Fecha AS FECHA,
        Concepto AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbNotas
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
        AND DOC IN ('ND', 'NC');

    Si usas la version 2005 o mayor entonces el subquery que usas en el primer query para calcular la cantidad de filas que cumplen la condicion lo puedes reemplazar por COUNT(*) OVER().

    SELECT
        'CUOTA' AS [TIPO MOV.],
        No AS [NO. DOC],
        Fechas AS FECHA,
        'CUOTA  # ' + CAST(NO AS nvarchar(10)) + '/'
        + CAST(COUNT(*) OVER() AS nvarchar(10)) AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbCuota
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
        
    UNION ALL
    
    SELECT
        'PAGO' AS [TIPO MOV.],
        Id_Cobro AS [NO. DOC],
        Fecha_Cobro AS FECHA,
        Descripcion AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbCOBRO
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
    
    UNION ALL
    
    SELECT
        DOC AS [TIPO MOV.],
        Id_Doc AS [NO. DOC],
        Fecha AS FECHA,
        Concepto AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbNotas
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
        AND DOC IN ('ND', 'NC');
    GO


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas




    miércoles, 10 de diciembre de 2014 21:21

Todas las respuestas

  • Hola,

    No hay mucho que hacer, sólo en las dos últimas consultas ambas salen de la misma tabla y sólo se diferencia por el tipo de documento. 

    Te dejo el código mejorado

    SELECT 
    	'CUOTA' AS 'TIPO MOV.', 
    	No AS 'NO. DOC', 
    	Fechas AS FECHA,
    	'CUOTA  # ' + CAST(NO AS NVARCHAR(10))  + '/' + CAST((SELECT COUNT(NO) FROM TbCuota WHERE Id_Prestamo = 1 AND Id_Compania = 1) AS NVARCHAR(10)) AS CONCEPTO, 
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbCuota 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1
    
    UNION ALL
    
    SELECT 
    	'PAGO' AS 'TIPO MOV.', 
    	Id_Cobro AS 'NO. DOC', 
    	Fecha_Cobro AS FECHA, 
    	Descripcion AS CONCEPTO, 
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbCOBRO 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1
    
    UNION ALL
    
    SELECT 
    	DOC AS 'TIPO MOV.', 
    	Id_Doc AS 'NO. DOC', 
    	Fecha AS FECHA, 
    	Concepto AS CONCEPTO,
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbNotas 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1

    PERO, veo ahí dos problemas. Primero, se entiende que este informe es para presentar los pagos realizados respecto a las deudas y además las NC y ND que han venido presentándose en el transcurso de la operación. Si lo haces tal cuál no tendrá un orden cronológico de los sucesos. Segundo, revisa la subconsulta para obtener el nro de cuota, siempre te saldrá el mismo nro.

    Te sugiero esto que incluso creo será más rápido

    DECLARE @Temporal table (idTemp int IDENTITY(1,1), tipomov nvarchar(100), numdoc nvarchar(100), fecha datetime, concepto nvarchar(100), valor decimal(19,5), mora decimal(19,5));
    
    /*INSERTAS TODOS LOS DATOS EN UNA TABLA TEMPORAL*/
    
    INSERT INTO @Temporal (tipomov, numdoc, fecha, concepto, valor, mora)
    SELECT 
    	'CUOTA' AS 'TIPO MOV.', 
    	No AS 'NO. DOC', 
    	Fechas AS FECHA,
    	'' AS CONCEPTO, 
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbCuota 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1;
    
    INSERT INTO @Temporal (tipomov, numdoc, fecha, concepto, valor, mora)
    SELECT 
    	'PAGO' AS 'TIPO MOV.', 
    	Id_Cobro AS 'NO. DOC', 
    	Fecha_Cobro AS FECHA, 
    	Descripcion AS CONCEPTO, 
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbCOBRO 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1;
    
    INSERT INTO @Temporal (tipomov, numdoc, fecha, concepto, valor, mora)
    SELECT 
    	DOC AS 'TIPO MOV.', 
    	Id_Doc AS 'NO. DOC', 
    	Fecha AS FECHA, 
    	Concepto AS CONCEPTO,
    	Capital + Interes AS VALOR, 
    	Mora AS MORA 
    FROM 
    	TbNotas 
    WHERE 
    	Id_Prestamo = 1 AND Id_Compania = 1;
    
    /*MUESTRAS LA TABLA TEMPORAL EN EL ORDEN CRONOLOGICO DE LAS OPERACIONES*/
    SELECT
    	tipomov, 
    	numdoc, 
    	fecha, 
    	CASE
    		WHEN tipomov = 'CUOTA' THEN idTemp /*Con esto devuelves el nro de cuota correlativo*/
    		ELSE concepto
    	END, 
    	valor, 
    	mora
    FROM
    	@Temporal
    ORDER BY
    	fecha;

    Salvo error u omisión esto estará OK

    Espero haberte ayudado con mi respuesta, si te fue útil no olvides marcarla como correcta.







    miércoles, 10 de diciembre de 2014 21:08
  • Lo primero seria cambiar todos los operadores UNION por UNION ALL ya que los cuatro conjuntos son mutuamente excluyentes.

    SELECT 'CUOTA' AS [TIPO MOV.]
    UNION
    SELECT 'PAGO' AS [TIPO MOV.]
    UNION
    SELECT 'NC' AS [TIPO MOV.]
    UNION
    SELECT 'ND' AS [TIPO MOV.];
    
    SELECT 'CUOTA' AS [TIPO MOV.]
    UNION ALL
    SELECT 'PAGO' AS [TIPO MOV.]
    UNION ALL
    SELECT 'NC' AS [TIPO MOV.]
    UNION ALL
    SELECT 'ND' AS [TIPO MOV.];

    Si chequeas el plan de ejecucion de tu query, notaras operadores de ordenacion (sort iterator) lo cual se usa para poder eliminar duplicados que es lo que tratas de hacer con UNION.

    Te recomiendo que uses los corchetes cuadrados ([]) o doble comilla (") para delimitar identificadores. Esto no tiene implicacion en el desempenio pero hara tu codigo mas legible.

    Las ultimas dos sentencias puedes reemplazarlas por una sola.

    SELECT
        'CUOTA' AS [TIPO MOV.],
        No AS [NO. DOC],
        Fechas AS FECHA,
        'CUOTA  # ' + CAST(NO AS nvarchar(10)) + '/'
        + CAST((
                SELECT
                    COUNT(NO)
                FROM
                    TbCuota
                WHERE
                    Id_Prestamo = 1
                    AND Id_Compania = 1
               ) AS nvarchar(10)) AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbCuota
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
        
    UNION ALL
    
    SELECT
        'PAGO' AS [TIPO MOV.],
        Id_Cobro AS [NO. DOC],
        Fecha_Cobro AS FECHA,
        Descripcion AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbCOBRO
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
    
    UNION ALL
    
    SELECT
        DOC AS [TIPO MOV.],
        Id_Doc AS [NO. DOC],
        Fecha AS FECHA,
        Concepto AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbNotas
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
        AND DOC IN ('ND', 'NC');

    Si usas la version 2005 o mayor entonces el subquery que usas en el primer query para calcular la cantidad de filas que cumplen la condicion lo puedes reemplazar por COUNT(*) OVER().

    SELECT
        'CUOTA' AS [TIPO MOV.],
        No AS [NO. DOC],
        Fechas AS FECHA,
        'CUOTA  # ' + CAST(NO AS nvarchar(10)) + '/'
        + CAST(COUNT(*) OVER() AS nvarchar(10)) AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbCuota
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
        
    UNION ALL
    
    SELECT
        'PAGO' AS [TIPO MOV.],
        Id_Cobro AS [NO. DOC],
        Fecha_Cobro AS FECHA,
        Descripcion AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbCOBRO
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
    
    UNION ALL
    
    SELECT
        DOC AS [TIPO MOV.],
        Id_Doc AS [NO. DOC],
        Fecha AS FECHA,
        Concepto AS CONCEPTO,
        Capital + Interes AS VALOR,
        Mora AS MORA
    FROM
        TbNotas
    WHERE
        Id_Prestamo = 1
        AND Id_Compania = 1
        AND DOC IN ('ND', 'NC');
    GO


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas




    miércoles, 10 de diciembre de 2014 21:21