PDA

Ver la Versión Completa : Consulta - MSSQL


Viet
08-10-2003, 19:05:27
Buenas, estoy algo mareado y no encuentro la vuelta a esta consulta

Trabajo con MSSQL

Tengo una tabla X que tiene los campos: Fecha, IdAccion ....

Y otra tabla Y donde tengo : Permitido(bit) , IdAccion.....

Lo que tengo que obtener son todos los registros de la tabla X que correspondan al dia de hoy, SI no existe otro reg del dia de hoy donde Permitido(haciendo un Inner join con Tabla Y) sea 0.

Lo primero es facil

Select *
From TablaX
Where
(datepart(dy,fecha)=datepart(dy,getdate()))


Pero no encuentro la forma de ver que no exista otro registro sin permiso para el mismo dia.

Alguna idea????

Muchas Gracias por su tiempo. ;)

Viet
08-10-2003, 19:17:47
Lo unico que se me ocurre es una subconsulta en el Where con :


Select *
From TablaX
Where
(datepart(dy,fecha)=datepart(dy,getdate())) and

Id not in(select * from tablaX x inner join tablaY y on
(x.IdAccion=y.IdAccion)
where y.Permitido=0 and (clausela de fecha) )

Pero la verdad me parece bastante ineficiente y cargado para el DBMS

Algo mas simple?

guillotmarc
08-10-2003, 19:31:14
Hola.

¿ Que es lo malo de : ?


Select X.*
From X
left outer join Y on X.IdAccion = Y.IdAccion
Where datepart(dy, X.Fecha)=datepart(dy, getdate())) and
Y.Permitido is null or Y.Permitido = 0


¿ Que quiere decir (clausula de fecha) al final de tu subconsulta ?

Saludos.

delphi.com.ar
08-10-2003, 19:41:08
Yo preferiría usar un NOT EXISTS, que según el motor (Desconozco lo que hace en MsSql) cuando encuentra al menos un registro deja cancela la subconsulta:
SELECT *
FROM TABLAX
WHERE datepart(dy,fecha)=datepart(dy,getdate())
AND NOT EXISTS (SELECT 1
FROM TABLAY
AND TABLAX.IDACCION = TABLAY.IDACCION
...)



Saludos!

Viet
08-10-2003, 19:45:03
Perdón ... no me he explicado bien...


Aclaracion ID no es clave de la tabla(solo es FK)

Ej tabla X

id IDAccion (omito fecha y los demas)
1 1
2 3
3 1
1 2
3 3
2 1

Tabla y

IdAccion Permitido
1 1
2 0
1 1

Solo tendria que darme

id
2
3
3
2


Osea solo tengo que mostrar los que no tienen en la otra tabla no permitido.....

Se entiende la diferencia ?

Viet
08-10-2003, 19:48:17
Gracias por el dato Delphi.com.ar ;)

Perdon Marc... si quise decir clausula

guillotmarc
08-10-2003, 19:55:43
Hola Viet.

Posteado originalmente por Viet
Perdon Marc... si quise decir clausula

Más bien me estaba preguntando que es lo que querias decir con cláusula de fecha, no que tenia un error de copiado.

Por cierto, por lo que comentas en el ultimo mensaje, la consulta que he propuesto debería servirte. Devuelve todas las filas de la tabla X del dia solicitado, que no tengan un registro relacionado en la tabla Y marcado como Permitido = 1.

Saludos.

guillotmarc
08-10-2003, 19:58:03
Creo que solo habría que añadirle la clausula distinct al select, para que devuelva el resultado que pedias en el ejemplo.

Saludos.

Viet
08-10-2003, 20:04:31
Marc si agrega la clausula me daria

id
2
3

Y necesito

id
2
3
3
2

y el problema es que no solo necesito el id, sino otra informacion asociada fecha, posicion, evento, y unos cuantos campos que necesito de esta consulta....

De todo modos muchas gracias ......

Ahora bien ..... se me ocurre que podria hacer la consulta en una tabla temporal y luego borrar los registros que tengan permitido en 0... pero creo que estoy en la misma... no?

guillotmarc
08-10-2003, 20:44:44
Hola.

Solo te quedaría eso si unicamente tuvieras select distinct id from .... Pero no con un select distinct X.* from ..., Puesto que también se selecciona la clave primaria de X, por lo que si tenemos dos registros con el mismo IdAccion, aparecerá dos veces incluso con el Distinct (debido a que la clave primaria al menos, será distinta).

El distinct lo ponemos, por si hay dos registros relacionados en Y, al hacernos la unión, no nos devuelva dos veces el mismo registro de X.

Realmente me gustaria que probases esta consulta, a ver si es lo que buscavas, o ver que problema debemos arreglar en ella :


Select distinct X.*
From X
left outer join Y on X.IdAccion = Y.IdAccion
Where datepart(dy, X.Fecha)=datepart(dy, getdate())) and
Y.Permitido is null or Y.Permitido = 0


Saludos.

Viet
08-10-2003, 21:06:05
Marc: desde ya muchas gracias por tu tiempo.


te cuento: obviamente que he supuesto la tabla X e Y ya que las originales son algo complicadas o mejor dicho largo de poner.... y no lo he probado antes ya que estoy manejando una cantidad de mas o menos 1.500.000 registros..... aunque no es excusa

bien... la consulta con la subconsulta me funciona bien(aunque no he logrado hacer funcionar el EXISTS que Delphi.com.ar me recomendo, no lo reconoce, y es MSSQL 7 ?? raro ... en fin)

Pero al poner la query con el left outter join no me devuelve ningun registro :confused:

lo que seria X.* , en realidad son varios campos , con una que otra funcion como dateadd y otros ..... puede ser por eso????

guillotmarc
08-10-2003, 21:58:26
Hola

Tampoco habia usado nunca el EXISTS, lo he mirado un poco en la documentación del MSSQL y me parece muy curiosa su sintaxis (La verdad es que no acabo de entenderla, no se indican los campos a comparar). Es bastante más comprensible el operador relacionado ANY.

Mirandolo bien, no creo que puedas usar el LEFT OUTER JOIN. Si la tabla relacionada (la Y) puede tener varios registros relacionados con la maestra X, y algunos de ellos marcan la operación como permitida y otras como no permitida, entonces el LEFT OUTER JOIN nos va a dejar pasar los registros de esa operación en X, puesto que cumplirán la condición cuando la unión se realize con los registros marcados como permitidos en Y.

Me parece que la única alternativa es utilizar una subconsulta, aunque puede ser un poco más sencilla de la que proponias :


Select *
From X
Where datepart(dy, Fecha) = datepart(dy, getdate()) and
IdAccion not in (select IdAccion from Y where Permitido = 0)


¿ Que te parece esta solución ?

Saludos.

Viet
08-10-2003, 22:08:13
Es lo que suponia Marc.... en realidad queda la consulta que tenia(la que tiene la subconsulta),.... ya que los registros que hay que filtrar son los que estan en la tabla X y que tengan alguno relacionado con Y que de Permitido=0...osea lo que estamos hablando....

Pregunta

code:--------------------------------------------------------------------------------
Select *
From X
Where datepart(dy, Fecha) = datepart(dy, getdate()) and
IdAccion not in (select IdAccion from Y where Permitido = 0)
--------------------------------------------------------------------------------

no es lo mismo que

Select *
From X inner join Y on (y.idaccion=x.idaccion)
where datepart(dy, Fecha) = datepart(dy, getdate())




???? creo que si es asi.... debo dejar la que puse antes

guillotmarc
08-10-2003, 22:22:26
Hola.

No es lo mismo, el resultado va a ser bastante distinto.

Un Inner Join es una unión, por lo que solo te va a coger los registros de X que tengan registros relacionados en Y. Además si tienes dos registros en Y relacionados con uno de X, en el resultado vas a tener dos veces el registro de X.

Esos dos registros de salida, se evaluan una vez uniendolo con el primer registro relacionado de Y, y la otra vez con el segundo. De forma que si el primer registro de Y permite la operación, vas a tener el registro X en la salida (independientemente de que el segundo registro de Y no permita la operación). Según lo tengo entendido, solo con que uno cualquiera de los registros relacionados en Y no permita la operación, ya no debes poder seleccionar el registro de X.

Eso es lo que hace la consulta con subconsulta que he puesto. Para empezar evalua todos los registros de X una sola vez (tengan uno, dos, o ningún registro relacionado en Y). Y para cada uno de los registros de X, comprueba de que no exista algún registro relacionado en Y donde lo marca como no Permitido (con que solo haya uno, ya falla la condición y no se selecciona el registro de X).

Espero que se entienda algo de lo que he escrito (es que no veo una forma mejor de explicarlo).

A ver si esta consulta hace lo que necesitas, sino es que no he entendido bien lo que debe ejecutar la consulta.

Saludos.

Viet
09-10-2003, 14:24:10
Esta muy claro Marc, y tienes toda la razon: no son resultados ni remotamente parecidas......

Lo que pasa es que en mi caso todos los registros de X tienen solo uno en Y.... osea que X.IdAccion es FK de Y.IdAccion que es Pk, por lo que el resultado si seria el mismo(va a esta altura no estoy seguro , je!).....

Todo esto pasa por que no he planteado el problema como es realmente, eso lo he hecho para tratar de eliminar de este Thread toda la complejidad de las tablas que manejo... lo cual me ha resultado en contra y le he hecho tipear y pensar mas de lo debido....

Moraleja: "Hay que plantear bien todas las consultas, en forma concisa pero dando los detalles del caso..... y no resumir las variables del problema".

Muchas Gracias por todo .... un Saludo ;)