I’m creating an application that allow users to create “group profiles.” A group profile represents one or more individuals. At the basic level, I’m using 2 tables: a parent table to group the profiles and a child table for the actual profiles. Assume that the profiles had age and gender details, how would I query the tables to get a list of parent table ids of:
- group profiles that represent just one profile?
- group profiles that represent a male and female between the ages of 25 and 30?
- group profiles that represent more than 2 profiles?
- etc.
At some point, I think I need to do a GROUP BY on the parent table id, but I’m a bit lost how to check the number of profiles a group profile has, how to meet certain criteria in the profiles (e.g. gender, etc.).
Here’s a sample table with some data:
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
DROP SCHEMA IF EXISTS `mydb` ;
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`foo_parent`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`foo_parent` ;
CREATE TABLE IF NOT EXISTS `mydb`.`foo_parent` (
`foo_parent_id` INT NOT NULL AUTO_INCREMENT ,
PRIMARY KEY (`foo_parent_id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`foo`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`foo` ;
CREATE TABLE IF NOT EXISTS `mydb`.`foo` (
`foo_id` INT NOT NULL AUTO_INCREMENT ,
`foo_parent_id` INT NOT NULL ,
`name` CHAR(50) NOT NULL ,
`gender` ENUM('male','female') NOT NULL ,
`age` INT NOT NULL ,
PRIMARY KEY (`foo_id`) ,
INDEX `foo_foo_parent_id` (`foo_parent_id` ASC) ,
CONSTRAINT `foo_foo_parent_id`
FOREIGN KEY (`foo_parent_id` )
REFERENCES `mydb`.`foo_parent` (`foo_parent_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
-- -----------------------------------------------------
-- Data for table `mydb`.`foo_parent`
-- -----------------------------------------------------
START TRANSACTION;
USE `mydb`;
INSERT INTO `mydb`.`foo_parent` (`foo_parent_id`) VALUES (1);
INSERT INTO `mydb`.`foo_parent` (`foo_parent_id`) VALUES (2);
COMMIT;
-- -----------------------------------------------------
-- Data for table `mydb`.`foo`
-- -----------------------------------------------------
START TRANSACTION;
USE `mydb`;
INSERT INTO `mydb`.`foo` (`foo_id`, `foo_parent_id`, `name`, `gender`, `age`) VALUES (1, 1, 'John Doe', 'male', 31);
INSERT INTO `mydb`.`foo` (`foo_id`, `foo_parent_id`, `name`, `gender`, `age`) VALUES (2, 1, 'Jane Doe', 'female', 29);
INSERT INTO `mydb`.`foo` (`foo_id`, `foo_parent_id`, `name`, `gender`, `age`) VALUES (3, 2, 'Billy Bob', 'male', 25);
INSERT INTO `mydb`.`foo` (`foo_id`, `foo_parent_id`, `name`, `gender`, `age`) VALUES (4, 2, 'Suzie', 'female', 27);
COMMIT;
Sample queries and results:
Example 1: get all foo_parent.id where the profiles represented by the group profile includes a “male” and a “female” returns 1 and 2.
Example 2: get all foo_parent.id where the profiles represented by the group profile includes a “male” and a “female” and are between the ages of 20 and 30 returns 2.
Also: if there is a blatantly obvious problem with this approach of grouping and querying profiles, please let me know.
You could try building your predicate counts e.g. ‘males between 20 and 30’ or ‘females between 20 and 30’ in an inline view and then referring to them in the where clause of the outer query. For example:
Example 1: get all foo_parent.id where the profiles represented by the group profile includes a “male” and a “female” returns 1 and 2:
Example 2: get all foo_parent.id where the profiles represented by the group profile includes a “male” and a “female” and are between the ages of 20 and 30 returns 2:
I’ve included the foo_parent table in these queries in case you want to include something like ‘has no males or females between 20 and 40’ or something like that.