entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

3votos

ejemplo :

este e sel resultado de un query que lo conforman varias tablas y restricciones las cuales digamos que me trae todos los resultados con estatus "1" y activo "A" de ciertas tablas que las uni con un inner join y se ve de esta manera
usuario fecha (yyyymmdd hhmmss) servicio status activo
220000011 2015-12-07 10:40:00.000 220004809 220000017 1 A
220000011 2015-12-20 10:40:00.000 220000697 220000017 1 A
220000011 2015-12-22 10:40:00.000 220001289 220000017 1 A
220000028 2015-12-02 12:10:00.000 220002509 220000050 1 A
220000028 2015-12-15 12:10:00.000 220003148 220000050 1 A

donde :

necesito hacer un barrido de ese query en cuanto a fechas si digamos en usuaio 1 que es 220000011 contiene 3 registros con fechas diferentes

usuario fecha (yyyymmdd hhmmss) servicio status activo
220000011 2015-12-07 10:40:00.000 220004809 220000017 1 A
220000011 2015-12-20 10:40:00.000 220000697 220000017 1 A
220000011 2015-12-22 10:40:00.000 220001289 220000017 1 A

comparar el registro 1 con el 2 y si este segundo registro es mayo a 10 dias que me lo muestre en este caso de la fecha de el primer registro 2015-12-07 y el segundo 2015-12-20 hay 13 dias de espacio quiero que me muestre el regiustro que supera esos dias y hacer esto con cada registor que se dio de el query pero solo de cada usuario en este caso solo fue de el 220000011 pero hay varios usuarios y quiero que solo se hagan las comparaciones solo de sus respectivas fechas nada mas

1voto

rach comentado

Me interesa esta pregunta...Alguien tiene alguna idea? yo igual leí que se podía con cursores, pero no estoy para nada familiarizada, alguien tendrá algún ejemplo? creen que se podría lograr si se hace con cursores?

0voto

Peter comentado

@rach Por favor abre una pregunta nueva con tus dudas.

Saludos.

3 Respuestas

2votos

hugo morales Puntos480
--SQL 2008//
ALTER PROCEDURE schema.nombre_procedure
as 

DECLARE ALRCURSOR CURSOR --DECLARACION DE CURSOR 
FOR 
    SELECT      CITA,SERVICIO,USUARIO,FE_CITA,PRES
        FROM     prueba 
        WHERE (PRESCRIPCION = 1) AND (ESTATUS_CITA = 'A') 
        GROUP BY CITA, SERVICIO,USUARIO,FE_CITA, PRES 
        ORDER BY FL_USUARIO , FE_CITA ASC    

DECLARE  @FLAG int ,@USUARIO int , @FECHA datetime ,@CITA INT,@SERVICIO INT , @PRESC INT ,@UACTUAL int , @FEACTUAL datetime ,@ACITA INT,@ASERVICIO INT , @APRESC INT 
--puse asi las variables puesto que las necesitare posterior mente para otra cosa 
set @FLAG = 0; --bandera = 0 comparar el primer dato

OPEN ALRCURSOR --ABRIR CURSOR 

while (@@FETCH_STATUS =0)
begin
  if(@FLAG=0)
       BEGIN
             FETCH ALRCURSOR INTO @CITA,@SERVICIO,@USUARIO,@FECHA, @PRESC ;   
             set @FLAG=1; 
      END 
  else  --  comparación del primer registro con el resto
       BEGIN      
            FETCH ALRCURSOR INTO @ACITA,@ASERVICIO,@UACTUAL,@FEACTUAL, @APRESC;  
                if(@USUARIO=@UACTUAL) -- mismo usuario, comparo fechas
                        BEGIN
                   IF ((select datediff (day,@FECHA,@FEACTUAL)AS DIFERENCIA )>30)
                BEGIN 

                                   PRINT @FEACTUAL 
                                   print @UACTUAL 
                                   print @ASERVICIO
                                   print @ACITA

                                   -- REALIZA LA ACCION SI ES QUE PASA DE LOS 30 que se sustituira con los insert en su respectiva tabla

                                    set @FLAG=0; 
                                END

                             ELSE 
                                BEGIN 
                               set @FLAG=0; 
                               END
                        END
               else ---ELSE DE USUARIO = AUSUARIO
                  BEGIN
                    SET @FLAG =0
                  END
               END
             END
  close ALRCURSOR
  deallocate ALRCURSOR

---------------hasta aqui termina el store ----

ya hice pruebas de los resultados obtenidos en la base de datos y en efecto los resultados de el store son correctos

2votos

Leonardo-Tadei Puntos227320

Hola @hugo morales ,

no hay manera de hacer esto solo con la query, porque no es posible en los RDBMS modernos mover hacia atrás al puntero de los resultados.

Si esta query se muestra desde algún software tuyo, podrías hacer una comparación del registro actual con el anterior (no con el siguiente) para determinar si se cumple la condición o no.

Si lo que te hace falta es que la query devuelva el resultado con las condiciones, deberías ejecutar una subquery que te devuelva el registro con la condición a cumplir o nulo, para determinar desde la query cuál se muestra. Es una query engorrosa de hacer pero no implosible si tenés los datos normalizados.

En la subquery deberías usar excluir el registro actual por ejemplo con un "mayor qué", con un LIMIT quedarte solo con el siguiente de ese subconjunto, y con una función que compare fechas ver si cumple la condición o no (se pueden usar campos de una query como comparadores de una subquery).

0voto

hugo morales comentado

si bueno la comparacion puede ser del registro actual al anterior digamos de el registro con la fecha mas reciente a la fecha mas antras estube leyendo acerca de cursores que podria igual implementarlo pero sigo sin digamos poder compararlo con el registro anterior y que cuando termine de hacerlo muestre si cumple o no con la condicion si no la cumple pasarse al anterior registro y realizar el mismo proceso hasta haber terminado con todos los registros de la query

3votos

blaDDI Puntos2260
# declarar mi curso con esta consulta ordeno por usuario y luego por fecha descendente(reciente a menos_reciente)
select *from usuario,fecha,servicio,estatus,activo,activo users a order by a.usuario,fecha desc
set bandera=0;
open cursor
    # bandera = 0; para no comparar el primer dato
    if(@bandera=0) then set@ausuario=usuario;set@afecha=fecha;set@aservicio=servicio;set@aestatus=estatus;set@aactivo=activo;
        else # comienza la comparación del primer registro con el resto
            if(@uactual=usuario)then    # si el usuario es el mismo comparo fechas
                if(DATEDIFF(@afecha,fecha)>10) # si la fecha es mayor a 10, ingreso datos a una tabla temporal
                    then insert into temp_table values ();
                end if; 
            # si los usuarios no son iguales asigno el nuevo usuario a las variables para poder compararlo con el resto
            else set@ausuario=usuario;set@afecha=fecha;set@aservicio=servicio;set@aestatus=estatus;set@aactivo=activo;
            end if;
    end if;
    # asigno el valor de @bandra =1 para para mantener el primer almacenado en las variables 
    # y comenzar hacer la comparaciones
    @bandera=1;     
close cursor
# devuelvo los usaurios con los registros que cumplan las condiciones
select *from temp_table;

Método similar al método de la burbuja, espero te sirva lo hice a la rápida


Comentario movido a respuesta.

0voto

hugo morales comentado

gracias por responder me dio una idea de como podria adaptarlo ya que lo voy a meter en un store procedure entonces la sintaxis cambia `por ejemplo de el if e igualar las variables a un campo de una tabla que salio de un query no me lo permite hacer me refiero a esto :

set@ausuario=usuario

donde usuario = bd.esquema.tabla.USUARIO

NO ME PERMITE me dice que no encuentra la tabla aun si le escribo toda la direccion la manera en como iguale las variables fue de esta manera

FETCH ALRCURSOR INTO @CITA,@SERVICIO,@USUARIO,@FECHA;

aun que no eh podido que me retorne los valores que necesito checando la logica de programacion trate de adaptar loq ue meti a lo que me comentaste blaDDI aun que aun sin algun cambio ademas que en el store procedure no me perminte la creacion de tablas temporales pues al momento d emandarlas a llamar me dice sql que no existe dicha tabla o que no la puedo mandar a llamar desde el store alguna otra idea?

ah y tambien en el codigo el primer valor se igualara al segundo cuando termine eso el segundo se igualara al tercer valor cuando termine el tercer valor se igualara al cuarto valor asi se ira hasta terminar con todo el resultado de el query , pues viendo el codigo puedo apreciar que efectivamente se hacer el varrido y la comparacion pero solo la comparaan con el primer resultado y ese con todos para una mejor vista de mi problema aqui un ejemplo

primer registro Abr 13 2015 10:20AM este se compara con el segundo registro
segundo registro Abr 14 2015 10:20AM este se compara con el tercer registro
tercer registro Abr 20 2015 10:20AM este se compara con el cuarto registro
cuarto registro may 13 2015 10:20AM este registro cumple con la regla de los 10 dias pues su anterior fecha la perteneciente a el mismo usuario fue Abr 20 2015 10:20AM y comparada con el 4 resitro es superior a 10 dias

entonces quiero que me muestre el 4 registro que cumple con la condicion

2votos

blaDDI comentado

CREATE DATABASE IF NOT EXISTS `pruebas`
USE `pruebas`;

-- Volcando estructura para procedimiento pruebas.Sp_prueba
DROP PROCEDURE IF EXISTS `Sp_prueba`;
DELIMITER //
CREATE PROCEDURE `Sp_prueba`()
    COMMENT 'Incremento Global de Cartera Ahorro Por Producto'
BEGIN
DECLARE done BOOLEAN DEFAULT FALSE;
DECLARE vusuario VARCHAR(50);
DECLARE vfecha TIMESTAMP;
DECLARE vservicio VARCHAR(10);
DECLARE vestatus ENUM('1','0');
DECLARE vactivo ENUM('A','I');
DECLARE c1 cursor FOR select usuario,fecha,servicio,estatus,activo from users order by usuario,fecha desc;

DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE;

CREATE TEMPORARY TABLE temp_table select *from users;
truncate temp_table;
set @bandera=0;                      
open c1;
    c1_loop: LOOP
        fetch c1 into vusuario,vfecha,vservicio,vestatus,vactivo;
    IF `done` 
        THEN LEAVE c1_loop;         
    END IF;
    if(@bandera=0) then set@ausuario=vusuario;set@afecha=vfecha;set@aservicio=vservicio;set@aestatus=vestatus;set@aactivo=vactivo;
        else 
            if(@ausuario=vusuario)then  
                if(ABS(DATEDIFF(@afecha,vfecha))>10)  
                    then  insert into temp_table (usuario,fecha,servicio,estatus,activo) 
                                         values (@ausuario,@afecha,@aservicio,@aestatus,@aactivo);
# esta linea te permite comparar 1 con 2,2 con 3,3 con 4.... 
                      #set@ausuario=vusuario;set@afecha=vfecha;set@aservicio=vservicio;set@aestatus=vestatus;set@aactivo=vactivo;select@afecha;
                #else set@ausuario=vusuario;set@afecha=vfecha;set@aservicio=vservicio;set@aestatus=vestatus;set@aactivo=vactivo;select@afecha;                                       
                end if; 
            else set@ausuario=vusuario;set@afecha=vfecha;set@aservicio=vservicio;set@aestatus=vestatus;set@aactivo=vactivo;
            end if;
    end if;
    set @bandera=1;
    END LOOP c1_loop;  
CLOSE c1;
select *from temp_table;
drop table temp_table;
END//
DELIMITER ;

-- Volcando estructura para tabla pruebas.users
DROP TABLE IF EXISTS `users`;
CREATE TABLE IF NOT EXISTS `users` (
  `idControl` int(11) NOT NULL AUTO_INCREMENT,
  `usuario` varchar(50) COLLATE utf8_bin DEFAULT NULL,
  `fecha` timestamp NULL DEFAULT NULL,
  `servicio` varchar(10) COLLATE utf8_bin DEFAULT NULL,
  `estatus` enum('1','0') COLLATE utf8_bin DEFAULT NULL,
  `activo` enum('A','I') COLLATE utf8_bin DEFAULT NULL COMMENT 'a=activo,I=inactivo',
  PRIMARY KEY (`idControl`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- Volcando datos para la tabla pruebas.users: 5 rows
REPLACE INTO `users` (`idControl`, `usuario`, `fecha`, `servicio`, `estatus`, `activo`) VALUES
    (5, '220000011', '2015-12-07 10:38:00', '220004809', '1', 'A'),
    (6, '220000011', '2015-12-20 10:41:00', '220000697', '1', 'A'),
    (7, '220000011', '2015-12-22 10:42:00', '220001289', '1', 'A'),
    (8, '220000028', '2015-12-02 12:07:00', '220002509', '1', 'A'),
    (9, '220000028', '2015-12-15 12:06:00', '220003148', '1', 'A');

Te dejo aquí una prueba que hice,chequéala y ve si te puede funcionar, puedes comparar el registro 1 con el 2, 2 con 3, 3 con 4....; solo quita el comentario, espero te ayude saludos

0voto

hugo morales comentado

muchas gracias fue de mucha ayuda el codigo que me pusiste y la logica de programacion que usaste me sirvio para implementarlo utilice parte de tu codigo y lo complemente con el mio ,fue asi que pude hacerlo gracias

1voto

blaDDI comentado

Que bien que te haya servido...
saludos

0voto

Peter comentado

hugo, Si esta no es la respuesta correcta, por favor comparte en una respuesta nueva el código exacto para la solución y seleccionala como correcto.

Saludos.

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta