Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > SQL
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 19-04-2016
darkamerico darkamerico is offline
Miembro
 
Registrado: dic 2010
Posts: 225
Poder: 14
darkamerico Va por buen camino
Wink Como realizar consulta SQL para validar si un numero no forma parte de un rango

Saludos amigos, estoy implementando un sistema de Horarios para mi Facultad, ya casi esta todo hecho; estoy usando el componente TPlanner de TMS Component Pack para XE10, el detalle de los horarios los tengo en una tabla llamada horario_detalle la cual tiene la siguiente estructura:



Algunos datos de la tabla mencionada:



El problema con todo sistema horarios es evitar que se asignen cursos que se crucen con otros previamente asignados y ese es el tema aqui, les explico:



Lo que necesito es mejorar la consulta sql que estoy usando para validar los casos de cruce:

Código SQL [-]
SELECT
horario_detalle.id_horariodet,
horario_detalle.posIniGrid,
horario_detalle.posFinGrid
FROM
horario_detalle
INNER JOIN curso ON horario_detalle.idcurso_fk = curso.id_curso
WHERE
horario_detalle.idsemestre_fk = :IDSemestre AND
horario_detalle.idcurr_fk = :IDCurr AND
horario_detalle.idfacultad_fk = :IDFacultad AND
horario_detalle.iddptoacad_fk = :IDDpto AND
horario_detalle.iddia = :IDDia AND
horario_detalle.posIniGrid BETWEEN :PosIni AND :PosFin AND
curso.ciclo = :Ciclo


Muchas Gracias por su atencion
Responder Con Cita
  #2  
Antiguo 19-04-2016
elrayo76 elrayo76 is offline
Miembro
 
Registrado: ene 2004
Ubicación: En la tierra, por eso mis archivos en la tierra y no en la nuebe...
Posts: 290
Poder: 21
elrayo76 Va por buen camino
Te paso parte del wehere que usaba yo en su momento para validar algo similar a lo tuyo. Yo lo hacia por fechas pero se puede itilizar con cualquier tipo de datos numéricos.

Código SQL [-]
     AND (   (    inCampoDesde <= CampoDesde                 
                  AND inCampoHasta >= CampoDesde
                )

             OR (    inCampoDesde >= CampoDesde
                 AND inCampoHasta <= CampoHasta
                )

             OR (    inCampoDesde <= CampoHasta
                 AND inCampoHasta >= CampoHasta
                )

             OR (    inCampoDesde <= CampoDesde
                 AND inCampoHasta >= CampoHasta
                )

Todo lo que comienza con 'in' lo debes reemplazar por lo que se ingresa desde tu aplicación. El resto son los campos de tu tabla.

Analiza lo que te paso y cualquier duda consultas.

Saludos,
El Rayo

PD: Si luego ven los administradores que esto le puede servir a muchos mas, lo pueden pasar como truco.
__________________
Si tienes una función o procedimiento con diez parámetros, probablemente hayas olvidado uno

Última edición por elrayo76 fecha: 19-04-2016 a las 21:33:18. Razón: Corrección del SQL
Responder Con Cita
  #3  
Antiguo 19-04-2016
elrayo76 elrayo76 is offline
Miembro
 
Registrado: ene 2004
Ubicación: En la tierra, por eso mis archivos en la tierra y no en la nuebe...
Posts: 290
Poder: 21
elrayo76 Va por buen camino
Olvide comentar que lo que puse en el mensaje anterior va a reemplazar al BETWEEN, ya que este no valida si solo se superpone una parte del rango, luego lo demas puede quedar como esta. Además yo esto lo usaba en consultas de Oracle.

Saludos,
El Rayo
__________________
Si tienes una función o procedimiento con diez parámetros, probablemente hayas olvidado uno
Responder Con Cita
  #4  
Antiguo 19-04-2016
darkamerico darkamerico is offline
Miembro
 
Registrado: dic 2010
Posts: 225
Poder: 14
darkamerico Va por buen camino
Red face Gracias amigo

Un caluroso saludo Rayo, mira puse en ejecución el código que me diste y sintácticamente funciona:

Código SQL [-]
SELECT
horario_detalle.id_horariodet,
horario_detalle.posIniGrid,
horario_detalle.posFinGrid
FROM
horario_detalle
INNER JOIN curso ON horario_detalle.idcurso_fk = curso.id_curso
WHERE
horario_detalle.idsemestre_fk = 1 AND
horario_detalle.idcurr_fk = 1 AND
horario_detalle.idfacultad_fk = 1 AND
horario_detalle.iddptoacad_fk = 1 AND
horario_detalle.iddia = 1 AND
((horario_detalle.posIniGrid>=0 AND horario_detalle.posFinGrid<=2)
  OR 
 (horario_detalle.posIniGrid>=0 AND horario_detalle.posFinGrid<=2)) AND
curso.ciclo = 10

Aquí asumo que un horario nuevo se quiere instalar el iddia=1 (Martes) entre las horas 0 (7:00am) a 2 (9:00am) cuando Ya existe un horario asignado a esa hora, y si, efectivamente arroja el id_horariodet correspondiente al horario asignado, pero que pasa si alguien quiere instalar un horario en iddia=1 entre las horas 1 (8:00am) y 3 (10:00am) donde existe cruce igualmente?


Saludos y Gracias
Responder Con Cita
  #5  
Antiguo 19-04-2016
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Curiosamente un motor sql deberia hacer esto super simple (ya que esto es manejo basico de relaciones), pero desafortunadamente todo depende de las abilidades programaticas de cada motor.

Esta es la forma basica (ej en python):

Código PHP:
>>> range(1,10)
>>> 
range(8,20)
>>> 
xs set(x)
>>> 
xs.intersection(y)
set([89]) 
El problema es como generar la lista de fechas en memoria, y eso depende de tu motor. La idea es hacer algo como:

Código SQL [-]
SELECT Fecha FROM FuncionGeneradora(Inicio, Fin)
-- 1 registro por cada hora entre inicio y fin

Y de ahi usas sql estandar para la interseccion
__________________
El malabarista.
Responder Con Cita
  #6  
Antiguo 19-04-2016
elrayo76 elrayo76 is offline
Miembro
 
Registrado: ene 2004
Ubicación: En la tierra, por eso mis archivos en la tierra y no en la nuebe...
Posts: 290
Poder: 21
elrayo76 Va por buen camino
Amigo darkamerico, te comento lo que hace lo que puse en el SQL.

1) Mira que no se crucen los datos estando los valores ingresados fuera de los rangos existentes o sean iguales a los límites.
2) Mira que no se crucen los datos estando los valores ingresados dentro del rango existente.
3) Mira que el rango tenga el desde dentro del rango existente pero el hasta puede estar dentro o fuera
4) Lo mismo que el anterior pero alrevez, el desde puede estar fuera pero el hasta dentro.

Pongo ejemplo con tu caso

Inicio = 2 / Fin = 4

Ingresan:

Inicio = 1 / Fin = 5 --> Primera validacion de mi SQL

Inicio = 2 / Fin = 5 --> Segunda validacion de mi SQL

Inicio = 2 / Fin = 4 --> Tercera validacion de mi SQL

Inicio = 1 / Fin = 4 --> Cuarta Validacion de mi SQL

Con este ejemplo creo que te debería quedar mas claro porque todas esas validaciones. Creeme que fue analizado mucho de hacerlo asi por tema de performance y no hay otra forma de hacerlo.


mamcx, como haces en tu código para validar si solo el inicio esta dentro del rango y el fin esta fuera o viceversa?. Por lo que entendi no lo puede hacer, dime si me equivoco.

Saludos,
El Rayo
__________________
Si tienes una función o procedimiento con diez parámetros, probablemente hayas olvidado uno
Responder Con Cita
  #7  
Antiguo 20-04-2016
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Lo que digo es que si se el motor que usa puede generar fechas en memoria puede usar sql estandar para hacer el chequeo. Osea, es armar una tabla en memoria con registros como:

Cita:
12-01-01 1pm
12-01-01 2pm
12-01-01 3pm
__________________
El malabarista.
Responder Con Cita
  #8  
Antiguo 20-04-2016
darkamerico darkamerico is offline
Miembro
 
Registrado: dic 2010
Posts: 225
Poder: 14
darkamerico Va por buen camino
Cool Una observacion final

La consulta implementada quedó como sigue:

Código SQL [-]
SELECT
horario_detalle.id_horariodet,
horario_detalle.posIniGrid,
horario_detalle.posFinGrid
FROM
horario_detalle
INNER JOIN curso ON horario_detalle.idcurso_fk = curso.id_curso
WHERE
horario_detalle.idsemestre_fk = :IDSemestre AND
horario_detalle.idcurr_fk = :IDCurr AND
horario_detalle.idfacultad_fk = :IDFacultad AND
horario_detalle.iddptoacad_fk = :IDDpto AND
horario_detalle.iddia = :IDDia AND
((:PosIni <= horario_detalle.posIniGrid AND :PosFin >= horario_detalle.posFinGrid)
  OR 
 (:PosIni >= horario_detalle.posIniGrid AND :PosFin <= horario_detalle.posFinGrid)
  OR
 (:PosIni <= horario_detalle.posFinGrid AND :PosFin >= horario_detalle.posFinGrid)
  OR 
 (:PosIni <= horario_detalle.posIniGrid AND :PosFin >= horario_detalle.posFinGrid)) AND
curso.ciclo = :Ciclo

Solo una observacion final: Si Existe un horario de hora=0 (7:00am) a hora=2 (9:00am) y quiero asignar un horario nuevo de 9:00am a 11:00am no me permite.

Un abrazo
Responder Con Cita
  #9  
Antiguo 20-04-2016
elrayo76 elrayo76 is offline
Miembro
 
Registrado: ene 2004
Ubicación: En la tierra, por eso mis archivos en la tierra y no en la nuebe...
Posts: 290
Poder: 21
elrayo76 Va por buen camino
Porque no te deja asignar el horario que quieres?. No se que es lo que te está devolviendo la consulta completa que pusiste.

Igualmente fijate que te equivocaste en un dato de la consulta. Te pongo tal cual como debes copiarla y pegarla.

Código SQL [-]
((:PosIni <= horario_detalle.posIniGrid AND :PosFin >= horario_detalle.posIniGrid)
  OR 
 (:PosIni >= horario_detalle.posIniGrid AND :PosFin <= horario_detalle.posFinGrid)
  OR
 (:PosIni <= horario_detalle.posFinGrid AND :PosFin >= horario_detalle.posFinGrid)
  OR 
 (:PosIni <= horario_detalle.posIniGrid AND :PosFin >= horario_detalle.posFinGrid))

Saludos,
El Rayo
__________________
Si tienes una función o procedimiento con diez parámetros, probablemente hayas olvidado uno
Responder Con Cita
  #10  
Antiguo 20-04-2016
darkamerico darkamerico is offline
Miembro
 
Registrado: dic 2010
Posts: 225
Poder: 14
darkamerico Va por buen camino
Talking Omg!

Grande Rayo, la cosa funcionó!!!!
Responder Con Cita
  #11  
Antiguo 20-04-2016
elrayo76 elrayo76 is offline
Miembro
 
Registrado: ene 2004
Ubicación: En la tierra, por eso mis archivos en la tierra y no en la nuebe...
Posts: 290
Poder: 21
elrayo76 Va por buen camino
Fue un gusto haberte ayudado, ya que a mi me han ayudado muchas veces.

Saludos,
El Rayo
__________________
Si tienes una función o procedimiento con diez parámetros, probablemente hayas olvidado uno
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Cómo escribir un número de forma exponencial? soammm Varios 1 29-10-2012 14:40:34
No se como realizar esta consulta minos SQL 2 01-10-2004 23:08:37
como buscar dentro de una consulta un texto que sea parte de la descripcion viajero2015 Conexión con bases de datos 1 15-11-2003 05:18:09
Como realizar esta Consulta en SQL Jose Manuel SQL 3 11-10-2003 16:01:02


La franja horaria es GMT +2. Ahora son las 14:34:55.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi