Retroceder   Foros del Web > Programación para sitios web > Bases de Datos > SQL Server

Respuesta
 
Herramientas Desplegado
Antiguo 09-may-2006, 15:55   #1 (permalink)
Moderador
Myakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy pronto
 
Avatar de Myakire
 
Fecha de Ingreso: noviembre-2002
Mensajes: 6.520
Enviar un mensaje por Yahoo  a Myakire
Optimizar un SP que traspone una tabla

Tengo un par de vistas que obtienen ciertos registros de la BD's, pero los obtengo por filas y los requiero por columnas, así que implementé un SP que traspone a mis necesidades la información, pero el problema es que se tarda mucho. Para una consulta que regresa 100 registros, se tarda casi 2 minutos para ejecutar el SP.

El detalle es que hago varias concatenaciones por que necesito la información con ciertas características:
1) Debe haber 4 columnas: M, P, T y O adicionales a la de la llave (NoParte). Las 3 columnas primeras son 'unicas y la 4a es el acumulado del resto de los valores del campo "Almacen"
2) La vista puede regresarme 1 o más registros pertenecientes a x número de almacenes, a veces 1 o 2 almacenes, a veces más y en cualquier orden.

Para forzar a que siempre se formen las 4 columnas en orden, hago acumulados y concatenaciones.

Si alguien pudiera darme una idea de como optimizar el SP, se lo agradecería mucho, el SP es el siguiente:


Código:
CREATE PROCEDURE sResumen_Assort_Inventario
AS
BEGIN

DECLARE @NoParte varchar(10)
DECLARE @NomAlmacen VARCHAR(50)
DECLARE @Valor float
DECLARE @Suma float

DECLARE @AlmacenM float
DECLARE @AlmacenP float
DECLARE @AlmacenT float


DECLARE @Count INT
DECLARE @GrantCount INT
DECLARE @Select VARCHAR(8000)
DECLARE @GrantSelect VARCHAR(8000)

DECLARE @CadAlmacenes VARCHAR(10)
DECLARE @Salida VARCHAR(8000)
DECLARE @IDAlmacen CHAR(1)

SET @GrantCount = 0
SET @GrantSelect = ''

DECLARE NumerosDeParte CURSOR SCROLL FOR
(SELECT NoParte
 FROM vw_Assort_Esp
 GROUP BY NoParte)

OPEN NumerosDeParte

FETCH FIRST FROM NumerosDeParte INTO @NoParte
WHILE @@FETCH_STATUS = 0
BEGIN
      DECLARE CurExistencias CURSOR SCROLL FOR 
      (SELECT Almacen, TonTotales, NoParte
      FROM vw_Assort_Inv
      WHERE NoParte = @NoParte)

      SET @Select = ''
      SET @Count = 0
      SET @CadAlmacenes = ''
      SET @Suma = 0
      SET @AlmacenM = 0
      SET @AlmacenP = 0
      SET @AlmacenT = 0
      
      OPEN CurExistencias
      FETCH FIRST FROM CurExistencias INTO @NomAlmacen, @Valor, @NoParte
      WHILE @@FETCH_STATUS = 0
      BEGIN
            SET @Count = @Count + 1
            SET @NomAlmacen = RTRIM(LTRIM(@NomAlmacen))
            IF @Count = 1
                SET @Select = @Select + ' SELECT NoParte=''' + RTRIM(LTRIM(@NoParte))+''''

            IF @NomAlmacen='M' OR @NomAlmacen='P' OR @NomAlmacen='T' 
            BEGIN
                 IF @NomAlmacen = 'M'
                       SET @AlmacenM = @Valor
                 IF @NomAlmacen = 'P'
                       SET @AlmacenP = @Valor
                 IF @NomAlmacen = 'T'
                       SET @AlmacenT = @Valor
            END
            ELSE
                 SET  @Suma = @Suma + @Valor

            SET @CadAlmacenes = @CadAlmacenes + @NomAlmacen

            FETCH NEXT FROM CurExistencias INTO @NomAlmacen, @Valor, @NoParte
      END

      CLOSE CurExistencias
      DEALLOCATE CurExistencias


      SET @Salida = ''
      DECLARE CurAlmacenes CURSOR SCROLL FOR  (SELECT Almacen FROM Almacenes WHERE Tipo='E')
      OPEN CurAlmacenes
      FETCH FIRST FROM CurAlmacenes INTO @IDAlmacen
      WHILE @@FETCH_STATUS = 0
      BEGIN
           IF CHARINDEX(@IDAlmacen, @CadAlmacenes)=0
           BEGIN
               IF RTRIM(LTRIM(@IDAlmacen))='M' OR RTRIM(LTRIM(@IDAlmacen))='P' OR RTRIM(LTRIM(@IDAlmacen))='T' 
               BEGIN
                   SET @Salida = @Salida +  ', ' + @IDAlmacen + '= ''0'''
               END
           END
           ELSE
               BEGIN
                    IF @IDAlmacen = 'M'
                       SET @Salida = @Salida +  ',M= '''+CONVERT(VARCHAR,@AlmacenM)+'''' 
                    IF @IDAlmacen = 'P'
                       SET @Salida = @Salida +  ',P= '''+CONVERT(VARCHAR,@AlmacenP)+'''' 
                    IF @IDAlmacen = 'T'
                       SET @Salida = @Salida +  ',T= '''+CONVERT(VARCHAR,@AlmacenT)+'''' 
               END
 
           FETCH NEXT FROM CurAlmacenes INTO @IDAlmacen
      END
      CLOSE CurAlmacenes
      DEALLOCATE CurAlmacenes

      IF @Suma > 0
          SET @Salida = @Salida +  ', NG= '''+CONVERT(VARCHAR,@Suma)+''''
      ELSE
          SET @Salida = @Salida +  ', NG= ''0'''

      IF @Count=0
           SET @Select = @Select + ' SELECT NoParte=''' + RTRIM(LTRIM(CONVERT(VARCHAR,@NoParte)))+'''' + @Salida
      ELSE 
           SET @Select = @Select + @Salida

      SET @Select = @Select + CHAR(13)

      SET @GrantCount = @GrantCount + 1
      IF @GrantCount = 1
            SET @GrantSelect = @Select
      ELSE
            SET @GrantSelect = @GrantSelect + CHAR(13) + ' UNION ' + CHAR(13)+  @Select

      FETCH NEXT FROM NumerosDeParte INTO @NoParte
END
PRINT(@GrantSelect)
EXEC(@GrantSelect)
CLOSE NumerosDeParte
DEALLOCATE NumerosDeParte
END
GO
Myakire está desconectado   Responder Citando
Antiguo 09-may-2006, 17:34   #2 (permalink)
Mickel tiene algunos puntos positivos de karma
 
Avatar de Mickel
 
Fecha de Ingreso: noviembre-2002
Ubicación: Lima, Peru
Mensajes: 4.703
Enviar un mensaje por Yahoo  a Mickel
Checa que las tablas que son llamadas por tus vistas vw_Assort_Esp y vw_Assort_Inv tengan NoParte en un index. Mas que eso... cambiar a SQL 2005, nomas...
__________________
Mi blog: http://www.mickel.biz. Mi Hi5: http://mickel.hi5.com
Mickel está desconectado   Responder Citando
Antiguo 09-may-2006, 19:49   #3 (permalink)
Moderador
Myakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy pronto
 
Avatar de Myakire
 
Fecha de Ingreso: noviembre-2002
Mensajes: 6.520
Enviar un mensaje por Yahoo  a Myakire
Las llaves estan correctas .... y según las pruebas que he hecho, SQL Server 2000 me da mejor desempeño que SQL 2005..... lástima
Myakire está desconectado   Responder Citando
Antiguo 09-may-2006, 21:35   #4 (permalink)
Moderador
u_goldman llegará a ser famoso muy prontou_goldman llegará a ser famoso muy prontou_goldman llegará a ser famoso muy prontou_goldman llegará a ser famoso muy pronto
 
Avatar de u_goldman
 
Fecha de Ingreso: noviembre-2002
Ubicación: LA
Mensajes: 7.366
Enviar un mensaje por MSN a u_goldman
El problema que yo veo master, son muchos cursores, entiendo que tienes que recorrer esos registros para hacerlos columnas, se me ocurre que si ya tienes tus vistas, puedes hacerle individualmente un group by al o los campos necesarios todo esto dentro de un select, no se que tanto mejoraría el rendimiento contra lo que ya tienes, y tampoco si realmente funcionará, pero algo tenía que decir

Ya nos contarás más cosas...
__________________
¿Qué darías por vivir un sueño?
u_goldman esta en línea ahora   Responder Citando
Antiguo 10-may-2006, 19:37   #5 (permalink)
Moderador
Myakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy pronto
 
Avatar de Myakire
 
Fecha de Ingreso: noviembre-2002
Mensajes: 6.520
Enviar un mensaje por Yahoo  a Myakire
mmmmmmmmmmmmmmmmm, pues no se, sería cosa de probar....

aunque te diré, en este momento estoy peleandome con una vista con no menos de 10 subconsultas y regresa 2000 registros perfectamente procesados en menos de 3 segundos. Por eso la extrañeza de el uso de esos 3 cursoritos anidados con tan pocos registros.

Por cierto .... ¿cómo diablos podría hacer para generar una columna con un consecutivo de número de registro en una consulta agrupada? .... sorry, es que no era solo una expresión eso de que me estaba "peleando", jejeje

Saludos y dejame "mastico" la sugerencia
Myakire está desconectado   Responder Citando
Antiguo 10-may-2006, 21:06   #6 (permalink)
Moderador
u_goldman llegará a ser famoso muy prontou_goldman llegará a ser famoso muy prontou_goldman llegará a ser famoso muy prontou_goldman llegará a ser famoso muy pronto
 
Avatar de u_goldman
 
Fecha de Ingreso: noviembre-2002
Ubicación: LA
Mensajes: 7.366
Enviar un mensaje por MSN a u_goldman
Cita:
Por cierto .... ¿cómo diablos podría hacer para generar una columna con un consecutivo de número de registro en una consulta agrupada? .... sorry, es que no era solo una expresión eso de que me estaba "peleando", jejeje
WHAT???

Creo que eso se traduce a lo mismo que lo que estás intentando para transponer tus registros verdad?

Se me acaba de ocurrir una idea...quizás en lugar de recorrer esos sets con cursores podrías tratar de usar tablas temporales y entonces hacer tus iteraciones a partir de ellas, me parece que sería más rápido... deja hago unas pequeñas pruebas.
__________________
¿Qué darías por vivir un sueño?
u_goldman esta en línea ahora   Responder Citando
Antiguo 15-may-2006, 15:39   #7 (permalink)
Moderador
Mithrandir llegará a ser famoso muy prontoMithrandir llegará a ser famoso muy pronto
 
Avatar de Mithrandir
 
Fecha de Ingreso: abril-2003
Mensajes: 12.108
No alcanzo a entender exactamente que es lo que pretendes lograr (por tanto cursor), pero creo que algo como esto se aproxima a lo que necesitas:
Código:
SELECT 
	NoParte,
	SUM(CASE WHEN Almacen = 'M' THEN TonTotales ELSE 0 END) AS AlmacenM,
	SUM(CASE WHEN Almacen = 'P' THEN TonTotales ELSE 0 END) AS AlmacenP,
	SUM(CASE WHEN Almacen = 'T' THEN TonTotales ELSE 0 END) AS AlmacenT,
	SUM(TonTotales) AS Total
FROM tabla
GROUP BY Almacen, NoParte
__________________
"El hombre, en su orgullo, creó a Dios a su imagen y semejanza."
Friedrich Nietzsche
Mithrandir está desconectado   Responder Citando
Antiguo 15-may-2006, 17:26   #8 (permalink)
Moderador
Myakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy prontoMyakire llegará a ser famoso muy pronto
 
Avatar de Myakire
 
Fecha de Ingreso: noviembre-2002
Mensajes: 6.520
Enviar un mensaje por Yahoo  a Myakire
Cita:
Iniciado por u_goldman
WHAT???

Creo que eso se traduce a lo mismo que lo que estás intentando para transponer tus registros verdad?

.....
Nop, jeje, es para otra cosa "más urgente" necesitaba (por que ya lo hice de otra forma) generar un campo extra a una vista con un número correspondiente al número de regfistro que le correspondiera dentro de ese grupo...... si ya se, estaba medio jalado, pero pasó lo mismo que con el SP de transpuesta.

Cita:
Iniciado por Mithrandir
No alcanzo a entender exactamente que es lo que pretendes lograr (por tanto cursor), pero creo que algo como esto se aproxima a lo que necesitas: ....
[suspiro]pues si[/suspiro], ya lo había hecho similar a esa forma, pero no me cuadran las cifras , el SP lo hace perfectamente, pero se tarda más de un minuto.
Supongo que ahora en lugar de gastarle tiempo al SP, mejor se lo dedico a la consulta

machas thanks y bueno, si alguien alguna vez necesita el algoritmo que transponga una tabla de filas a columnas, el SP que publiqué al principio lo hace, la idea supongo que esta bien: Leer las filas, formar la consulta, concatenar y ejecutar consultas UNION, aunque seguramente debe haber otra forma. Ahora que tenga chance (oportunidad) veré como optimizar el caso de la tranpuesta, por ahora creo que me regresaré a la consulta.

Les debo unas birras (te las perdiste Mith, hasta el otro año en San Marcos)
Myakire está desconectado   Responder Citando
Respuesta
No hay votos aún.


Herramientas
Desplegado

Normas de Publicación
No puedes crear nuevos temas
No puedes responder temas
No puedes subir archivos adjuntos
No puedes editar tus mensajes

BB code is Activado
Caritas están Activado
[IMG] está Activado
Código HTML está Desactivado


La Zona horaria es GMT -6. Ahora son las 00:42.


Message Board Statistics

LinkBacks Enabled by vBSEO 3.1.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93