none
consulta sql

    Question

  • Hola como están, pido por favor una colaboración u orientación con lo siguiente, tengo una tabla donde en el primero campo tiene una fecha sin horas, minutos y segundos luego 2 campos con valores por ejemplo valor1 y valor2, estoy intentando realizar una consulta donde me arroje en las columnas los campos valor1 y valor2 y en las filas me arroje rangos por fechas por ejemplo F1 hasta F2 entonces las sumatoria de todos los registros por valor1 y todos por valor2.

    Lo que no se es como agrupar para que genere los rangos por ejemplo yo le digo rangos cada 2 meses o 3 meses.  Bueno tratare de ilustrarlo

    fecha,valor1,varlo2

    2010/01/01,5,6

    2010/02/01,6,8

    2010/03/01,4,3

    2010/04/01,3,6

    2010/02/01,4,9

    2010/03/01/9,4

    y la idea es si se le da cada 2 meses

    2010/01/01 hasta 2010/02/28,15,23

    2010/03/01 hasta 2010/04/30,7,9

    El formato de la fecha para este ejemplo es yyyy/mm/dd, ahora no se es como mostrar el rango de fechas y que salga ordenado porque al parecer cuando paso esto a excel no aparece ordenado por el rango sino en desorden, entiendo que para excel esto no es fecha sino texto.

     

    Friday, July 09, 2010 4:42 PM

Answers

  • Hola.

    Sí se puede indicar un case que mire más de un campo. En tu caso, lo que haría sería preparar una tabla de tramos de meses, con su fecha de inicio del tramo y su fecha de fin, así conviertes un rango en un identificador y resuelves el problema de tener que construir ese case, que además en tu caso es algo que puede variar por lo que comentas.

    En cualquier caso, yo evitaría crear tablas temporales para esto, primero intentaría lo de la tabla de rangos.

    create table Rangos (Rango varchar(100), Fecha_Desde smalldatetime, Fecha_Hasta smalldatetime)
    go
    
    insert Rangos values ('2010/01/01 hasta 2010/02/28', '20100101', '20100228')
    --Y así con todos los rangos que quieras insertar
    go
    
    select
     Rangos.Rango 
     sum(tabla.valor1) as SumaValor1,
     sum(tabla,valor2) as SumaValor2
    from tabla inner join
     Rangos on tabla.Fecha between Rangos.Fecha_Desde and Rangos.Fecha_Hasta
    where tabla.Fecha between '20080101' and '20100101'
    group by 
     Rango
    order by Rangos.Rango
    
    go
    


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Tuesday, July 13, 2010 11:58 PM

All replies

  • Hola.

    Tienes que construir una sentencia con un case que establezca esos rango de dos o tres meses y luego agrupar por ello. Para que salga ordenado, usas un order by. Sería más o menos así:

    select
     Rango = case 
      when fecha between '20100101' and '20100228' then '2010/01/01 hasta 2010/02/28'
      when fecha between '20100301' and '20100430' then '2010/03/01 hasta 2010/04/30'
      when fecha between '20100501' and '20100630' then '2010/04/01 hasta 2010/06/30'
    				/*... rellenar el resto de meses*/
     end
     sum(valor1) as SumaValor1,
     sum(valor2) as SumaValor2
    from tabla
    group by 
     case 
      when fecha between '20100101' and '20100228' then '2010/01/01 hasta 2010/02/28'
      when fecha between '20100301' and '20100430' then '2010/03/01 hasta 2010/04/30'
      when fecha between '20100501' and '20100630' then '2010/04/01 hasta 2010/06/30'
    				/*... rellenar el resto de meses*/
     end
    order by Rango
    

    Si no lo logras, nos dices.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Saturday, July 10, 2010 6:38 AM
  • Gracias por tu respuesta, sin embargo seria dinamica la generacion de esta sentencia supongo.
    Monday, July 12, 2010 2:16 AM
  • Hola.

    No entiendo a lo que te refieres. Si es a que debe ser sql dinámico, no, no tiene porqué. Tienes varias formas de conseguirlo, sólo te apuntaba esa consulta como ejemplo.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Monday, July 12, 2010 6:35 PM
  • Hola que pena contigo, esta propuesta deriva otra pregunta,  lo que ocurre es que esta sentencia debe estar en un procedimiento entonces para generarla quiero decir que debo construir la sentencia dinamicamente, ahora el problema de este metodo asi como esta es que si lo que se solicita es un rango de años pero cada 2 meses que es el problema que se me presentó, al enviarle la sentencia desde el programa, el parametros de tipo varchar o nvarchar no aguanto el tamaño, entonces por eso digo que debo replantearlo pero dentro del sp, por ejemplo saber cual es el rango y el intervalo para ese campo y por medio de un ciclo recorrer los años para este ejemplo y crear la consulta normal por ejemplo

    select campos from x  where fecha>= tal and fecha <tal,

    e ir insertando en una tabla temporal tal vez, se me ocurre esta como usa solución. Pero.. resulta que también es posible crear case when por varios campos.   La pregunta del año entonces sería, al resultado de insertar consultas a traves de un ciclo, ¿cómo después hago para generar por el otro campo se lo debo hacer al resultado de lo que he almacenado en la nuevo tabla o.

    Lo que quiero decir es si la primera consulta la puedo hacer

    select campos from x where fecha>= tal and fecha <tal y lo anterior dentro de un ciclo de 2 fechas por cierto intervalo e ir insertando en una tabla temporal, al final le digo un select a toda la tabla y listo pero..

    si se le tiene que hacer un case when a otro campo debo hacer el mismo ciclo por un intervalo y hacerlo a los registros obtenidos del ciclo anterior?, es ahí donde no entiendo.

    Disculpa por preguntar tanto pero estas sentencias me confunden

    Tuesday, July 13, 2010 4:06 PM
  • Hola.

    Sí se puede indicar un case que mire más de un campo. En tu caso, lo que haría sería preparar una tabla de tramos de meses, con su fecha de inicio del tramo y su fecha de fin, así conviertes un rango en un identificador y resuelves el problema de tener que construir ese case, que además en tu caso es algo que puede variar por lo que comentas.

    En cualquier caso, yo evitaría crear tablas temporales para esto, primero intentaría lo de la tabla de rangos.

    create table Rangos (Rango varchar(100), Fecha_Desde smalldatetime, Fecha_Hasta smalldatetime)
    go
    
    insert Rangos values ('2010/01/01 hasta 2010/02/28', '20100101', '20100228')
    --Y así con todos los rangos que quieras insertar
    go
    
    select
     Rangos.Rango 
     sum(tabla.valor1) as SumaValor1,
     sum(tabla,valor2) as SumaValor2
    from tabla inner join
     Rangos on tabla.Fecha between Rangos.Fecha_Desde and Rangos.Fecha_Hasta
    where tabla.Fecha between '20080101' and '20100101'
    group by 
     Rango
    order by Rangos.Rango
    
    go
    


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Tuesday, July 13, 2010 11:58 PM
  • Que pena estaba resolviendo otros tema,  agradezco esta respuesta no la he probado aún, de hecho ya la voy a probar, sin embargo me gustaría saber si así mismo es posible pegarle otras tablas donde además de fechas son valores numéricos por ejemplo de 1 a 5 de 6 a 10.  La duda es, necesariamente se le debe indicar el rango de fechas, pensé que al estar creados los rangos en la otra tabla de alguna manera se podría extraer la información sin necesidad de especificarla,  porque esto me indica que de alguna manera hay que recorrer la tabla de rangos para poder extraer los datos.

    Ahora bien si hubiese otra tabla el cuál se debe obtener rangos numericos, supongo que habría que hacer lo mismo que es crear otra tabla adicionarle los campos y sus rangos y luego dinámicamente hacer el inner join?

     

    Gracias por su colaboración

    Thursday, August 12, 2010 6:27 PM
  • Hola.

    No es necesario indicarle el filtro de fechas, podría tomarse del rango. Pero a nivel de rendimiento, es mejor acotarlo. Y en cuanto a si es posible realizar otros rangos que sean numéricos, la respuesta es sí, no hay mayor inconveniente en ello.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Thursday, August 12, 2010 7:25 PM
  • Compañero agradezco tu colaboración pero realmente estoy aburrido con este query, realmente no se aún como implementarlo, en resumen el problema es este.

    <!-- @page { margin: 0.79in } P { margin-bottom: 0.08in } -->

    Originalmente existe el siguiente query:

     select sum (c1), sum(c2),

    case

    when c3>=fecha1 and c3<fecha2 then 'algo'

    when c3>=fecha3 and c3<fecha4 then 'algo2'

    when c3>=fecha5 and c3<fecha6 then 'algo3' end as fecha,

    case

    when c4>=1 and c4<5 then 'algo1'

    when c4>=5 and c4<10 then 'algo1'

    when c4>=10 and c4<15 then 'algo1' end as periodo

    from tabla group by fecha,periodo

    Esta instrucción está siendo enviado desde en aplicativo cliente y que ahora lo estoy cambiando a un procedimiento almacenado.

     Se me han presentado los siguientes inconvenientes, dentro de la sentencia select vienen hasta 2 campos con instrucciones case, para evaluar varias condiciones, ocurre que algunas veces este “case” hace que aumente el tamaño de caracteres de la cadena, ocasionando que al asignarlo al procedimiento almacenado se reviente por que el tipo nvarchar del parametro solo permite 4000 caracteres.

    Entonces decidí cambiar y realizar estos procesos por dentro del procedimiento almacenado.

    ¿He ahí el problema como diablos transformo esa sentencia original a otra que haga lo mismo?

    Lo que pude lograr es conocer por ejemplo cuando un campo es fecha obtener los rangos limites inferior y superior y luego un intervalo por ejemplo cada 2 meses. Luego lo que hago es un ciclo while donde realizo querys condicionando las fechas del ciclo a las fechas calculadas a través del while. Eso lo estoy metiendo en una tabla hasta que al final simplemente hago un select de la tabla resultante.

    ¿El problema ahora es como le pego el otro campo case? ¿hay otra forma de hacerlo mas óptima?, ¿lo que me has dicho se ajusta a esta problemática?

    Wednesday, August 18, 2010 1:54 PM
  • Hola.

    No uses sql dinámico. Crea el procedimiento almacenado igual que la consulta que estás indicando y podrás añadir tantos case como precises.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Thursday, August 19, 2010 11:44 AM
  • Hola entiendo que no debo usar sql dinamico pero no veo como, la consulta que coloqué como ejemplo es solo eso, realmente las fechas pueden aumentar hasta 20 rangos o mas,  el case del campo numerico tambien es variable por esta razon creo que sí debo usar sql dinamico.   ahora si intento crear concatenando cadenas para crear los case de los campos se surge el problema de que las cadenas de tipo nvarchar son máximo de 4000 caracteres y estas sentencias a veces son muy grandes superando esta capacidad.

    Realmente que pena incomodar tanto con este mismo tema pero es que hmmmm no se que mas hacer.

     

    Ahora estoy probando otra opción y es la siguiente cree 2 tablas para los 2 campos y ahí coloque los rangos, luego cree un combinatoria entre estas 2 tablas,  después recorro esta tabla creando una sentencia por cada rango de las 2 tablas uniendo lo criterios con " and " y la paso a una tabla y después que temine hago un select de la tabla resultante.  Creo que este no es el mejor método pero por favor escucho sugerencias.

    Thursday, August 19, 2010 4:10 PM
  • Hola.

    Por eso insisto en que no uses SQL dinámico. Construye tu procedimiento de forma fija, no tardarás tanto y evitarás el problema. También puedes crear funciones definidas por el usuario para contraer los case, pero tendrías que escribir el código de todos modos.

    La otra idea que expones se basa en lo mismo, con lo que mi opinión al respecto es la misma.


    Alberto López Grande (Visita mi blog en http://qwalgrande.blogspot.es/)
    Thursday, August 19, 2010 4:17 PM