Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General »

Ayuda con consulta

Estas en el tema de Ayuda con consulta en el foro de Bases de Datos General en Foros del Web. Un saludo y bueno también de camino felices fiestas a los usuarios del foro, en principio comento lo que tengo hecho y a lo que ...
  #1 (permalink)  
Antiguo 23/12/2008, 11:33
 
Fecha de Ingreso: diciembre-2007
Mensajes: 149
Antigüedad: 16 años, 4 meses
Puntos: 1
Pregunta Ayuda con consulta

Un saludo y bueno también de camino felices fiestas a los usuarios del foro, en principio comento lo que tengo hecho y a lo que quiero llegar pero no puedo, ¿OK?.

Nota: no es para un ejercicio de clase ni nada por el estilo es un pique mío interno jojojo

TABLAS:
DROP TABLE IF EXISTS usuario;
CREATE TABLE usuario(
id_usuario int(11) auto_increment,
dni varchar(9) not null unique,
nombre varchar(100) not null unique,
profesion varchar(100) not null,
anio_nac int(11) not null,
sexo varchar(6) not null,
direccion varchar(150) not null,
cp int(11) not null,
poblacion varchar(50) not null,
barrio varchar(50) not null,
telf_1 int(11) not null,
telf_2 int(11),
email varchar(50) not null,
nick varchar(15) not null,
pass varchar(15) not null,
horas_disponibles int(11) default 0,
PRIMARY KEY(id_usuario)
)ENGINE=InnoDB;

DROP TABLE IF EXISTS movimiento;
CREATE TABLE movimiento(
id_movimiento int(11) auto_increment,
id_usuario int(11) not null,
id_actividad int(11) not null,
oferta tinyint(1),
demanda tinyint(1),
fecha date,
horas_empleadas int(11) default 0, -- horas empleadas en el movimiento
estado tinyint(1),
PRIMARY KEY(id_movimiento)
)ENGINE=InnoDB;
Necesito una consulta que me realize lo siguiente:

SELECCIONA LAS PERSONAS QUE DEMANDEN ALGO Y TENGAN UNA HORA MINIMA DISPONIBLE Y QUE ADEMAS NO HAYAN SOLICITADO
MAS DE 2 HORAS:



Pero he llegado hasta la siguiente consulta:
CONSULTA 1:

SELECCIONA LOS USUARIOS QUE TENGAN ALGÚN MOVIMIENTO Y MUESTRE LAS HORAS USADAS POR CADA UNO:

SELECT usuario.id_usuario,usuario.nombre,movimiento.id_ac tividad,SUM(movimiento.horas_empleadas) AS TOTAL_HORAS,movimiento.id_usuario
FROM usuario,movimiento
WHERE movimiento.id_usuario = usuario.id_usuario
GROUP BY movimiento.id_usuario

RESULTADO CONSULTA 1:

id_usuario nombre id_actividad TOTAL_HORAS id_usuario
1 uss1 4 8 1
2 uss2 1 2 2
3 uss3 1 2 3

Hasta aquí bien pero ahora necesito "filtrar" los campos que tengan un TOTAL_HORAS mayor que 2, el problema es que he provado muchas consultas, y claro la tabla TOTAL_HORAS es un alias y no está en la tabla creada así que mysql me devuelve un error, no sé entonces si se puede con mysql hacer eso, así que quiero que echeis una mano o si no acabaré haciendolo con php y ya está, solo quería saber si había forma con mysql. Al grano esto es lo que yo conseguí:

SELECT usuario.id_usuario,usuario.nombre,movimiento.id_ac tividad,SUM(movimiento.horas_empleadas) AS TOTAL_HORAS,movimiento.id_usuario
FROM usuario,movimiento
WHERE movimiento.id_usuario = usuario.id_usuario
AND TOTAL_HORAS < 8
GROUP BY movimiento.id_usuario;

Evidentemente esto no funciona pero era para que lo vieseis.

Gracias por vuestra atención. Por cierto a que molan lo coloritos ^^_

Última edición por sk1one; 23/12/2008 a las 11:42
  #2 (permalink)  
Antiguo 23/12/2008, 11:51
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Ayuda con consulta

Prueba esto (no lo he probado)

SELECT usuario.id_usuario,usuario.nombre,movimiento.id_ac tividad,SUM(movimiento.horas_empleadas) AS TOTAL_HORAS,movimiento.id_usuario
FROM usuario inner join movimiento
on movimiento.id_usuario = usuario.id_usuario
GROUP BY movimiento.id_usuario having SUM(movimiento.horas_empleadas) < 8
  #3 (permalink)  
Antiguo 24/12/2008, 04:57
 
Fecha de Ingreso: diciembre-2007
Mensajes: 149
Antigüedad: 16 años, 4 meses
Puntos: 1
Respuesta: Ayuda con consulta

Cita:
Iniciado por jurena Ver Mensaje
Prueba esto (no lo he probado)

SELECT usuario.id_usuario,usuario.nombre,movimiento.id_ac tividad,SUM(movimiento.horas_empleadas) AS TOTAL_HORAS,movimiento.id_usuario
FROM usuario inner join movimiento
on movimiento.id_usuario = usuario.id_usuario
GROUP BY movimiento.id_usuario having SUM(movimiento.horas_empleadas) < 8
SI!!! es lo que yo necesitaba , pero.. peudo hacerte un par de preguntas?.

1. ¿Que es lo que hace HAVING SUM?, esto lo desconozco.
2. ¿Hacia falta un INNER JOIN ? ¿Se puede con movimiento.id_usuario = usuario.id_usuario simplemente?.

Y muchas gracias!!! ^^

SELECT usuario.id_usuario, usuario.nombre, movimiento.id_actividad, SUM( movimiento.horas_empleadas ) AS TOTAL_HORAS, movimiento.id_usuario
FROM usuario
INNER JOIN movimiento ON movimiento.id_usuario = usuario.id_usuario
GROUP BY movimiento.id_usuario
HAVING SUM( movimiento.horas_empleadas ) <8
LIMIT 0 , 30
  #4 (permalink)  
Antiguo 24/12/2008, 05:21
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Ayuda con consulta

Cita:
1. ¿Que es lo que hace HAVING SUM?, esto lo desconozco.
2. ¿Hacia falta un INNER JOIN ? ¿Se puede con movimiento.id_usuario = usuario.id_usuario simplemente?.


SELECT usuario.id_usuario, usuario.nombre, movimiento.id_actividad, SUM( movimiento.horas_empleadas ) AS TOTAL_HORAS, movimiento.id_usuario
FROM usuario
INNER JOIN movimiento ON movimiento.id_usuario = usuario.id_usuario
GROUP BY movimiento.id_usuario
HAVING SUM( movimiento.horas_empleadas ) <8
LIMIT 0 , 30

Trataré de responderte en el orden inverso.
2) Puede usarse también movimiento.id_usuario = usuario.id_usuario, y el resultado es el mismo; pero, en mi opinión, es más eficiente y deja el código más claro INNER JOIN ... ON... He leído decir a quienes de esto saben, que, si los índices están bien hechos, la consulta se optimiza con INNER JOIN. También he leído a otros que también saben sobre el tema decir que el parseador corrige y el resultado es el mismo en ambos casos. Yo, aunque no fuera cierto lo primero (creo que sí lo es, aunque no soy técnico), sólo por la claridad del código, prefiero usar INNER JOIN... ON... en estos casos. Creo que es un buen hábito para construir la sintaxis SQL.

1) HAVING se usa tras GROUP BY y te permite consultar (restringir, condicionar) datos resultantes de la agrupación. Por eso se escribe detrás. Si tú buscaras un dato existente en la tabla o que pudiera deducirse a partir de los datos de los registros (uno a uno), usarías el WHERE y lo pondrías antes del GROUP BY... Pero lo que tú buscas es algo que resulta de agrupar y por tanto debes emplear el HAVING... El SUM(...) es la función aritmética agrupada sobre la que buscas el resultado.
Tú te traes los nombres y los movimientos; con el where podrías encontrar los movimientos cuya cantidad fuera, por ej., superior a 1000, pero no la suma de movimientos cuya cantidad fuera superior a 1000, pues eso sólo puedes hacerlo después de agrupar los resultados de la consulta por algún criterio (en este caso el id del usuario) y sumar, y no antes...
Naturalmente, es posible y frecuente hacer consultas con WHERE antes del GROUP BY y con HAVING detrás. Con el where buscas un dato que no es fruto de la agrupación, y con having el que es resultado de la misma (ej.el usuario cuya suma de operaciones sólo superiores a 1000 sea una cantidad superior a 100000: SELECT usuario, SUM(operacion) tot FROM tabla WHERE operacion > 1000 GROUP BY idusuario HAVING tot > 100000). En cuanto al uso de SUM (...) tras el HAVING en lugar del alias TOTAL_HORAS, como puedes ver en este ejemplo.

SELECT usuario.id_usuario, usuario.nombre, movimiento.id_actividad, SUM( movimiento.horas_empleadas ) AS TOTAL_HORAS, movimiento.id_usuario
FROM usuario
INNER JOIN movimiento ON movimiento.id_usuario = usuario.id_usuario
GROUP BY movimiento.id_usuario
HAVING TOTAL_HORAS < 8
LIMIT 0 , 30[/QUOTE]

es más bien una precaución. No siempre los alias funcionan, y si además cambias de MySQL a otro motor puedes encontrarte con algún problema. Pero prueba si quieres utilizando el alias como te he puesto en el ejemplo anterior.

Última edición por jurena; 24/12/2008 a las 08:13
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 09:04.