MySQL SELECT DISTINCT con múltiples JOINS

Estoy tratando de SELECCIONAR y obtener un conjunto de resultados único, de una base de datos MySQL, como se muestra a continuación. Creo que mi problema es que no entiendo las uniones IZQUIERDAS lo suficientemente bien. O tal vez necesito usar un enfoque de combinación diferente.

Aquí hay una descripción de la base de datos.

tbAdult (Adults) tiene x número de tbchild (Children) y utiliza una tabla de referencias cruzadas llamada tbadultchildxref. Esta mesa tiene una tecla f tanto para adultos como para niños. Tengo que usar una tabla de referencia externa, porque hay una relación de muchos a muchos entre estas dos tablas, y hay otros datos que se mantienen en la referencia externa, que eliminé para simplificar.

A su vez, cada Niño pertenece a un Programa (tblprogram).

Cada Programa tiene x número de Cámaras (tblCamera). Nuevamente, tengo que usar una tabla de referencias cruzadas entre tblProgram y tblCamera debido a una relación de muchos a muchos y otras razones.

A lo que estoy tratando de llegar es a una lista única de cámaras para un padre determinado.

Por ejemplo, el padre 675 tiene tres hijos, los ID de niño 789,788, 789 y 4. Esos tres hijos, a su vez, pertenecen a los ID de programa 5, 6 y XNUMX.

ID de programa 4 tiene ID de cámara 1,2,3 ID de programa 5 tiene ID de cámara 4,5,6 ID de programa 6 tiene ID de cámara 1,6,7,8

Lo que me gustaría que fuera el conjunto de resultados es 1,2,3,4,5,6,7,8

He intentado diferentes combinaciones de SELECT DISTINCT, LEFT JOINS en las distintas tablas de referencias externas, etc., pero parece que no puedo conseguirlo.

Mi otro problema, en el camino, es que necesito verificar los campos "Activo" en Adulto, Niño y Programa para igualar = 1 (verdadero) para el conjunto de resultados.

Gracias de antemano.

CREATE TABLE `tbladult` (
 `pkAdultID` int(11) NOT NULL AUTO_INCREMENT,
 `fldAdultActive` tinyint(1) DEFAULT '1',
 `fldAdultLogin` varchar(30) DEFAULT NULL,
 `fldAdultPassword` varchar(45) DEFAULT NULL,
 `fldAdultFirstName` varchar(60) DEFAULT NULL,
 `fldAdultLastName` varchar(60) DEFAULT NULL,
 PRIMARY KEY (`pkAdultID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;


/*Table structure for table `tblchild` */

CREATE TABLE `tblchild` (
 `pkChildID` int(11) NOT NULL AUTO_INCREMENT,
 `fldChildActive` tinyint(4) DEFAULT NULL,
 `fldChildFirstName` varchar(45) DEFAULT NULL,
 `fldChildLastName` varchar(45) DEFAULT NULL,
 `fkChildProgram` int(1) DEFAULT NULL,
 PRIMARY KEY (`pkChildID`),
 KEY `FK_tblchild` (`fkChildProgram`),
 CONSTRAINT `FK_tblchild` FOREIGN KEY (`fkChildProgram`) REFERENCES `tblprogram` (`pkProgramID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;


/*Table structure for table `tbladultchildxref` */

CREATE TABLE `tbladultchildxref` (
 `pkAdultChildxRefID` int(11) NOT NULL AUTO_INCREMENT,
 `fldAdultChildxRefActive` tinyint(1) DEFAULT '1',
 `fkAdultID` int(11) DEFAULT NULL,
 `fkChildID` int(11) DEFAULT NULL,
 PRIMARY KEY (`pkAdultChildxRefID`),
 KEY `FK_tbladultchildxref` (`fkAdultID`),
 KEY `FK_tbladultchildxref2` (`fkChildID`),
 CONSTRAINT `FK_tbladultchildxref` FOREIGN KEY (`fkAdultID`) REFERENCES `tbladult` (`pkAdultID`),
 CONSTRAINT `FK_tbladultchildxref2` FOREIGN KEY (`fkChildID`) REFERENCES `tblchild` (`pkChildID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;



/*Table structure for table `tblprogram` */

CREATE TABLE `tblprogram` (
  `pkProgramID` int(11) NOT NULL AUTO_INCREMENT,
  `fldProgamActive` tinyint(1) DEFAULT '1',
  `fldProgramName` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`pkProgramID`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;

/*Table structure for table `tblcamera` */

CREATE TABLE `tblcamera` (
 `pkCameraID` int(11) NOT NULL AUTO_INCREMENT,
 `fldCameraName` varchar(50) DEFAULT NULL,
 `fldCameralocation` varchar(50) DEFAULT NULL,
 `fldCameraURL` varchar(250) DEFAULT NULL,
 PRIMARY KEY (`pkCameraID`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;


/*Table structure for table `tblprogramcameraxref` */

CREATE TABLE `tblprogramcameraxref` (
 `pkProgramCameraXrefID` int(11) NOT NULL AUTO_INCREMENT,
 `fkProgramID` int(11) DEFAULT NULL,
 `fkCameraID` int(11) DEFAULT NULL,
 PRIMARY KEY (`pkProgramCameraXrefID`),
 KEY `FK_tblprogramcameraxref` (`fkProgramID`),
 KEY `FK_camerasforprograms` (`fkCameraID`),
 CONSTRAINT `FK_camerasforprograms` FOREIGN KEY (`fkCameraID`) REFERENCES `tblcamera`     (`pkCameraID`),
 CONSTRAINT `FK_tblprogramcameraxref` FOREIGN KEY (`fkProgramID`) REFERENCES `tblprogram` (`pkProgramID`)

preguntado el 21 de mayo de 12 a las 19:05

Agregar el SQL que está ejecutando sería útil para que otros lo ayuden. -

Herramienta útil de muchos tipos de uniones encontradas aquí -

2 Respuestas

No se necesitan LEFT JOIN:

SELECT DISTINCT tblprogramcameraxref.fkcameraid
FROM tblprogramcameraxref
JOIN tblprogram ON tblprogramcameraxref.fkprogramid = tblprogram.pkprogramid
  AND tblprobram.fldProgramActive = 1
JOIN tblchild ON tblprogramcameraxref.fkprogramid = tblchild.fkchildprogram 
  AND tblchild.fldChildActive = 1
JOIN tbladultchildxref ON tblchild.pkchildid = tbladultchildxref.fkchildid
  AND tbladultchildxref.fldAdultChildxRefActive = 1
WHERE tbladultchildxref.fkadultid = 675

Además, es posible que desee comprobar la fkChildProgram int(1) DEFAULT NULL, en tblchild - la columna a la que hace referencia se define como int(11)

En este punto, no debería necesitar verificar si Adulto está activo (ya que ese es el criterio de búsqueda con el que comenzó), pero si debe hacerlo, simplemente agregue esto al final de la lista de unión:

JOIN tbladult ON tbladultchildxref.fkadultid = tbladult.pkadultid
  AND tbladult.fldAdultActive = 1

contestado el 21 de mayo de 12 a las 19:05

+1 - se me adelantó. Es posible que desee agregar un AND fldChildActive = 1 AND fldProgramActive = 1 a la cláusula WHERE también. - Eric Petroelje

Gracias por esta solución y también por señalar las fallas en la definición de mi columna. Puedo ver ahora, la lógica de mirar mi esquema desde un enfoque de abajo hacia arriba. Ahora puedo ver dónde funcionan los múltiples, pero simples JOIN ON. Gracias de nuevo - tim murphree

Es una descripción larga. Si he entendido la pregunta correctamente, esta consulta debería ayudarlo:

SELECT DISTINCT pcref.fkCameraID
FROM tbladult adult,
     tblchild child,
     tbladultchildxref acref,
     tblprogram prog,
     tblcamera camera,
     tblprogramcameraxref pcref
WHERE adult.pkAdultID = 675
AND adult.fldAdultActive = TRUE
AND adult.pkAdultID = acref.fkAdultID
AND acref.fkChildID = child.pkChildID 
AND child.fldChildActive = TRUE
AND child.fkChildProgram = prog.pkProgramID 
AND prog.fldProgamActive = TRUE
AND prog.pkProgramID = pcref.fkProgramID 

contestado el 22 de mayo de 12 a las 08:05

Gracias por esto. En realidad, esta solución tenía dos cosas muy interesantes al respecto. Por un lado, se hizo en el mismo orden en que tengo mi esquema, o en otras palabras, un enfoque de arriba hacia abajo. Y dos, esto no usó ningún JOINS en absoluto. Al final, elegí una de las otras respuestas, pero pensé que esta también era una gran respuesta. Como soy un novato en SQL y sigo tratando de aprender cuándo usar diferentes JOINS, quería obligarme a entender completamente todas las opciones dadas. Sin embargo, en algún caso en el futuro, también tendré en cuenta este enfoque directo. - tim murphree

@TimMurphree Siento que los JOINS son buenos, pero cuando puedes lograr cosas de una manera más simple, ¿por qué optar por las complicadas? ;-)- JHS

@TimMurphree ciertamente hay JOIN en la consulta anterior, aunque implícita. Utilizando SELECT ... FROM table1, table2 es de hecho una UNIÓN CRUZADA entre table1 y table2. agregando WHERE table1.key1 = table2.key2 lo convierte en un convencional INNER JOIN. - PinnyM

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.