Tim Murphree
Tim Murphree

Reputation: 635

MySQL SELECT DISTINCT with multiple JOINS

I'm trying to SELECT, and get a unique result set, from a MySQL database, as shown below. My problem is, I think, I don't understand LEFT Joins well enough. Or, maybe I need to use a different Join approach.

Here's a description of the database.

tbAdult (Adults) have x number of tbchild (Children) , and uses a cross-ref table called tbadultchildxref. This table has an f-key to both Adult and Child. I have to use an x-ref table, because there's a many-to-many relationship between these two tables, and there's other data that's keep in the x-ref, which I have removed for simplicity.

In turn, each Child belongs to a Program (tblprogram).

Each Program has x number of Cameras (tblCamera). Again, I have to use an x-ref table between tblProgram and tblCamera due to a many-to-many relationship, and other reasons.

What I am trying to get at, is a unique list of Cameras for a given Parent.

For example, Parent 675 has three children, Child ID's 789,788, and 789. Those three children, in turn, belong to Program ID's 4, 5, and 6.

Program ID 4 has Camera ID's 1,2,3 Program ID 5 has Camera ID's 4,5,6 Program ID 6 has Camera ID's 1,6,7,8

What I would like the result set to be is 1,2,3,4,5,6,7,8

I have tried different combinations of SELECT DISTINCT, LEFT JOINS on the various x-ref tables, etc. but I just can't seem to get it.

My other problem, along the way, is I need to check the "Active" fields in Adult, Child, and Program to equal = 1 (true) for the result set.

Thanks in advance.

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`)

Upvotes: 0

Views: 6629

Answers (2)

JHS
JHS

Reputation: 7871

It is a long description. If I have understood the question correctly this query should help you -

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 

Upvotes: 0

PinnyM
PinnyM

Reputation: 35533

No LEFT JOINs necessary:

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

Also, you may want to check the fkChildProgram int(1) DEFAULT NULL, in tblchild - the column it references is defined as int(11)

At this point you shouldn't really need to check if Adult is active (since that's the search criteria you started with), but if you must - just add this to the end of the join list:

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

Upvotes: 3

Related Questions