none
Cambiar lógica de Una consulta. RRS feed

  • Pregunta

  • Hola expertos en t-sql :D

    Me dejaron un procedimiento que toma demasiado tiempo para ejecutar, como ejemplo les dejo estas 2 tablas temporales que incluyen el procedimiento y que he detectado que toman mayor tiempo, el tema es que veo que las dos consultas tienen la misma estructura salvo al ultimo donde buscan un valor diferente en otra tabla temporal también creada en el procedimiento.

    Quisiese saber si hay algún modo de cambiar la estructura para agilizar un poco la consulta

    --CREAR TABLA 2                CREATE TABLE TAB_TEMPORAL2 ([id_cita] [int] ,[renaes][int],[id_persona][int],
    [periodo][varchar](8),[fichafam][varchar](10),[ubigeo][varchar](6),
    [edad][int],[tip_edad][varchar](10),[SEXO][char](1),[ET][varchar](3),[FI][varchar](10),[id_profesional] [int],
    [Atencion][int],[Num_vivos][int],[Num_muertos][int],[Etapa][int] ) 
    insert into TAB_TEMPORAL2

    select t.id_cita, t.renaes, t.id_persona, t.periodo, t.fichafam, t.ubigeo, t.edad_reg EDAD, t.id_tipedad_reg TIP_EDAD, 
    t.id_genero SEXO, t.id_etnia ET, t.id_financiador FI, t.id_profesional, 2 Atencion ,
    Num_vivos =
    case
    when exists(select tm1.cod_item from #TEMPORAL1 tm1 where t.id_cita=tm1.id_cita and tm1.cod_item in ('Z370','Z373','Z381')  ) then 1
    when exists(select tm1.cod_item from #TEMPORAL1 tm1 where t.id_cita=tm1.id_cita and tm1.cod_item in ('Z372','Z376','Z384')  ) then 2
    when exists(select tm1.cod_item from #TEMPORAL1 tm1 where t.id_cita=tm1.id_cita and tm1.cod_item in ('Z375','Z387')  ) then 3
    end ,
    Num_muertos =
    case
    when exists(select tm2.cod_item from #TEMPORAL1 tm2 where t.id_cita=tm2.id_cita and tm2.cod_item in ('Z371','Z373','Z376')  ) then 1
    when exists(select tm2.cod_item from #TEMPORAL1 tm2 where t.id_cita=tm2.id_cita and tm2.cod_item in ('Z374')  ) then 2
    when exists(select tm2.cod_item from #TEMPORAL1 tm2 where t.id_cita=tm2.id_cita and tm2.cod_item in ('Z377')  ) then 3
    end,
    Etapa =
    case
    when id_tipedad_reg='A' and edad_reg between 10 and 11 then 1
    when id_tipedad_reg='A' and edad_reg between 12 and 17 then 2
    when id_tipedad_reg='A' and edad_reg between 18 and 29 then 3
    when id_tipedad_reg='A' and edad_reg between 30 and 59 then 4
    end

    from [dbo].[TRAMAHIS_DTSG] t where (t.id_tipedad_reg='A' and (t.edad_reg between 10 and 59) and t.id_genero='F') and (
    (t.id_tipitem='D' and t.cod_item in ('59430','Z3921','Z390'))
    and exists(select tm.cod_item from #TEMPORAL2 tm where t.id_cita=tm.id_cita and tm.valor_lab IN ('PDS') ) 
    and exists(select tm1.cod_item from #TEMPORAL2 tm1 where t.id_cita=tm1.id_cita and tm1.valor_lab IN ('TRA') ) )

    --CREAR TABLA 3

    select t.id_cita, t.renaes, t.id_persona, t.periodo, t.fichafam, t.ubigeo, t.edad_reg EDAD, t.id_tipedad_reg TIP_EDAD, 
    t.id_genero SEXO, t.id_etnia ET, t.id_financiador FI, t.id_profesional, 3 Atencion,
    Num_vivos =
    case
    when exists(select tm1.cod_item from #TEMPORAL1 tm1 where t.id_cita=tm1.id_cita and tm1.cod_item in ('Z370','Z373','Z381')  ) then 1
    when exists(select tm1.cod_item from #TEMPORAL1 tm1 where t.id_cita=tm1.id_cita and tm1.cod_item in ('Z372','Z376','Z384')  ) then 2
    when exists(select tm1.cod_item from #TEMPORAL1 tm1 where t.id_cita=tm1.id_cita and tm1.cod_item in ('Z375','Z387')  ) then 3
    end ,
    Num_muertos =
    case
    when exists(select tm2.cod_item from #TEMPORAL1 tm2 where t.id_cita=tm2.id_cita and tm2.cod_item in ('Z371','Z373','Z376')  ) then 1
    when exists(select tm2.cod_item from #TEMPORAL1 tm2 where t.id_cita=tm2.id_cita and tm2.cod_item in ('Z374')  ) then 2
    when exists(select tm2.cod_item from #TEMPORAL1 tm2 where t.id_cita=tm2.id_cita and tm2.cod_item in ('Z377')  ) then 3
    end,
    Etapa =
    case
    when id_tipedad_reg='A' and edad_reg between 10 and 11 then 1
    when id_tipedad_reg='A' and edad_reg between 12 and 17 then 2
    when id_tipedad_reg='A' and edad_reg between 18 and 29 then 3
    when id_tipedad_reg='A' and edad_reg between 30 and 59 then 4
    end
    into TAB_TEMPORAL3 
    from [dbo].[TRAMAHIS_DTSG] t where (t.id_tipedad_reg='A' and (t.edad_reg between 10 and 59) and t.id_genero='F') and (
    (t.id_tipitem='D' and t.cod_item in ('59430','Z3921','Z390'))
    and exists(select tm.cod_item from #TEMPORAL2 tm where t.id_cita=tm.id_cita and tm.valor_lab IN ('FAM') ) 
    and exists(select tm1.cod_item from #TEMPORAL2 tm1 where t.id_cita=tm1.id_cita and tm1.valor_lab IN ('TRA') ) )

      
    lunes, 25 de junio de 2018 13:53

Todas las respuestas

  • Hola AlexanderC1992.

    Lo primero, porque utilizas tablas, cuando puedes utilizar o Tablas de expresión Común (CTE), o tablas en memoria.

    Tal cual lo has presentado, te resultará más fácil utilizar declare @tabla_temporal2 table(……);

    se utiliza exactamente igual, pero no se genera una tabla en la bbdd, y será más rápida.

    Por otra parte, si utilizas exists la sintaxis es select * from tabla. Exists va a utilizar la clave primara para saber si el registro existe. Si no defines una clave primaria, tendrá que recorrer el montón para hacerlo.

    CREATE TABLE TAB_TEMPORAL2
    ([id_cita]        [INT],
     [renaes]         [INT],
     [id_persona]     [INT],
     [periodo]        [VARCHAR](8),
     [fichafam]       [VARCHAR](10),
     [ubigeo]         [VARCHAR](6),
     [edad]           [INT],
     [tip_edad]       [VARCHAR](10),
     [SEXO]           [CHAR](1),
     [ET]             [VARCHAR](3),
     [FI]             [VARCHAR](10),
     [id_profesional] [INT],
     [Atencion]       [INT],
     [Num_vivos]      [INT],
     [Num_muertos]    [INT],
     [Etapa]          [INT],
     PRIMARY KEY([id_cita])
    );

    Eso hará que funcione más rápido. Luego dado que todo sale de la tabla [dbo].[TRAMAHIS_DTSG] es probable que algún índice le vendría de perlas. Si mantienes la misma estructura a temporal1 para tm2_cpditem, le vendría de lujo.

    Un saludo

    lunes, 25 de junio de 2018 20:35
  • Gracias Javi, lo de create table si lo tengo definido totalmente y siempre agilizo con eso (este no es mi script), lo que yo preguntaba es que 

    from [dbo].[TRAMAHIS_DTSG] t where (t.id_tipedad_reg='A' and (t.edad_reg between 10 and 59) and t.id_genero='F') and (
    (t.id_tipitem='D' and t.cod_item in ('59430','Z3921','Z390'))
    and exists(select tm.cod_item from #TEMPORAL2 tm where t.id_cita=tm.id_cita and tm.valor_lab IN ('FAM') ) 
    and exists(select tm1.cod_item from #TEMPORAL2 tm1 where t.id_cita=tm1.id_cita and tm1.valor_lab IN ('TRA') ) )

    from [dbo].[TRAMAHIS_DTSG] t where (t.id_tipedad_reg='A' and (t.edad_reg between 10 and 59) and t.id_genero='F') and (
    (t.id_tipitem='D' and t.cod_item in ('59430','Z3921','Z390'))
    and exists(select tm.cod_item from #TEMPORAL2 tm where t.id_cita=tm.id_cita and tm.valor_lab IN ('PDS') ) 
    and exists(select tm1.cod_item from #TEMPORAL2 tm1 where t.id_cita=tm1.id_cita and tm1.valor_lab IN ('TRA') ) )

    En estas dos son lo mismo, salvo el exists, el cual cambia al final de la penúltima linea de ambas consultas . Una busca 'PDS' y en el otro script busca 'FAM'. Yo quisiera que esta consulta se haga en un solo bloque para que haga un solo barrido, ya que al final a estas dos tablas le hacen un UNION.

    martes, 26 de junio de 2018 13:56
  • Hola AlexanderC1992:

    from [dbo].[TRAMAHIS_DTSG] t where (t.id_tipedad_reg='A' and (t.edad_reg between 10 and 59) and t.id_genero='F') and (
    (t.id_tipitem='D' and t.cod_item in ('59430','Z3921','Z390'))
    and exists(select tm.cod_item from #TEMPORAL2 tm where t.id_cita=tm.id_cita and tm.valor_lab IN ('FAM', 'TRA', 'PDS') ) 

    A lo mejor me he perdido con los in las causisticas, pero la clausula in recoge una serie de valores, por tanto solo tengo que preguntar si existen esa serie de valores.

    Te pongo un ejemplo porque al final es exactamente lo mismo.

    create table d (id int identity(1,1), valor varchar(2));
    go
    insert into d (valor) values ('f0'),('g'),('h1'),('i'),('j'),('k'),('l'),('m');
    go
    /* opcion 1 
    Relaciono la tabla por su id y le pregunto
    */
    select d.* from d
    join (select id from d) as o on d.id= o.id
    where 
    d.id > 1 
    and d.valor in ('h1','i','j')
    /* opcion 2
    relaciono la tabla por los valores que quiero que tengan (similar a in)
     */
    select d.* from d
    join (select valor from d) as o on d.valor= o.valor
    where 
    d.id > 1 
    and d.valor in ('h1','i','j')
    /* in */
    select d.* from d
    where 
    d.id > 1 
    and d.valor in ('h1','i','j')
    /* exists */
    select d.* from d
    
    where 
    d.id > 1 
    and d.valor in ('h1','i','j')
    and exists (select valor from d)
    /* exists con asterisco */
    select d.* from d
    where 
    d.id > 1 
    and d.valor in ('h1','i','j')
    and exists (select * from d)
    
    

    Si relacionas temporal2 con [dbo].[TRAMAHIS_DTSG] t ya esta. No?

    martes, 26 de junio de 2018 16:34