我正在创建一个允许用户创建“群组个人资料”的应用程序。组配置文件代表一个或多个个人。在基本级别,我使用2个表:父表用于对配置文件进行分组,子表用于实际配置文件。假设配置文件具有年龄和性别详细信息,我将如何查询表以获取父表id的列表:
在某些时候,我认为我需要在父表id上执行GROUP BY,但是我有点迷失了如何检查组配置文件具有的配置文件数,如何满足配置文件中的某些条件(例如性别等。)。
以下是包含一些数据的示例表:
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;
示例查询和结果:
示例1:获取所有foo_parent.id
,其中组配置文件所代表的配置文件包含“男性”,“女性”返回1和2.
示例2:获取所有foo_parent.id
,其中由组配置文件表示的配置文件包含“男性”和“女性”,年龄介于20到30之间,返回2。
另外:如果这种分组和查询配置文件的方法存在明显的问题,请告诉我。
答案 0 :(得分:0)
您可以尝试构建谓词计数,例如在内联视图中,“20到30之间的男性”或“20到30之间的女性”,然后在外部查询的where子句中引用它们。例如:
示例1:获取所有foo_parent.id,其中组配置文件表示的配置文件包含“male”,“female”返回1和2:
select t.foo_parent_id
from
(
select fp.foo_parent_id,
sum(case when f.gender = 'Male' then 1 else 0 end) as males,
sum(case when f.gender = 'Female' then 1 else 0 end) as females,
sum(case when f.gender = 'Male' and f.age between 20 and 30 then 1 else 0 end) as twenties_males,
sum(case when f.gender = 'Female' and f.age between 20 and 30 then 1 else 0 end) as twenties_females
from foo_parent fp
left outer join foo f on f.foo_parent_id = fp.foo_parent_id
group by fp.foo_parent_id
) t
where t.males > 0 and t.females > 0;
示例2:获取所有foo_parent.id,其中由组配置文件表示的配置文件包含“男性”和“女性”,年龄介于20和30之间,返回2:
select t.foo_parent_id
from
(
select fp.foo_parent_id,
sum(case when f.gender = 'Male' then 1 else 0 end) as males,
sum(case when f.gender = 'Female' then 1 else 0 end) as females,
sum(case when f.gender = 'Male' and f.age between 20 and 30 then 1 else 0 end) as twenties_males,
sum(case when f.gender = 'Female' and f.age between 20 and 30 then 1 else 0 end) as twenties_females
from foo_parent fp
left outer join foo f on f.foo_parent_id = fp.foo_parent_id
group by fp.foo_parent_id
) t
where t.twenties_males > 0 and t.twenties_females > 0;
我在这些查询中包含了foo_parent表,以防你想要包含“20到40之间没有男性或女性”之类的东西。
答案 1 :(得分:0)
另一种方法是为您查询的每组数据创建别名(在本例中为性别),然后按照以下示例加入同一组:
select
grp.foo_parent_id
from
foo m
,foo f
,foo_parent grp
where
m.foo_parent_id = grp.foo_parent_id
and f.foo_parent_id = grp.foo_parent_id
and m.gender = 'male'
and f.gender = 'female'
select
grp.foo_parent_id
from
foo m
,foo f
,foo_parent grp
where
m.foo_parent_id = grp.foo_parent_id
and f.foo_parent_id = grp.foo_parent_id
and m.gender = 'male'
and f.gender = 'female'
and m.age between 20 and 30
and f.age between 20 and 30
答案 2 :(得分:-1)
对于:示例1:获取所有foo_parent.id,其中由组配置文件表示的配置文件包含“男性”,“女性”返回1和2.
SELECT f.foo_parent_id
FROM (
SELECT f.foo_parent_id, f.gender
FROM mydb.foo AS f
GROUP BY f.foo_parent_id, f.gender
) AS f
GROUP BY f.foo_parent_id
HAVING COUNT(f.foo_parent_id) >= 2;
对于:示例2:获取所有foo_parent.id,其中由组配置文件表示的配置文件包含“男性”和“女性”,年龄介于20到30之间,返回2。
SELECT f.foo_parent_id
FROM (
SELECT f.foo_parent_id, f.gender
FROM mydb.foo AS f
WHERE f.age BETWEEN 20 AND 30
GROUP BY f.foo_parent_id, f.gender
) AS f
GROUP BY f.foo_parent_id
HAVING COUNT(f.foo_parent_id) >= 2;
但是,我不确定这是最好的方法。
对于:代表两个以上个人资料的群组配置文件?
SELECT f.foo_parent_id
FROM mydb.foo AS f
GROUP BY f.foo_parent_id
HAVING COUNT(*) > 2;