繁体   English   中英

此SELECT应该使用联接还是子查询?

[英]Should this SELECT use a join or a subquery?

SELECT u.users_username, u.givenname, u.familyname, u.studentassent, u.parentconsent, u.birthdate, u.gender
FROM users AS u
JOIN classes_users as c
ON c.users_username = u.users_username
JOIN classes_users as x
ON c.classes_id = x.classes_id
WHERE x.users_username = "johnny" AND x.role = "teacher"

要么

SELECT u.users_username, u.givenname, u.familyname, u.studentassent, u.parentconsent, u.birthdate, u.gender
FROM users AS u
WHERE u.users_username
IN (
    SELECT c.users_username
    FROM classes_users as c
    JOIN classes_users as x
    ON c.classes_id = x.classes_id
    WHERE x.users_username = "johnny" AND x.role = "teacher"
)

我以为第一个语句更好,但是我仍在学习如何编写更好的SQL语句,在所有内部情况上还不清楚,在这种情况下,使一个语句比另一个语句更好的是什么。

如果有比我编写的两种方法更好的编写方法,请告诉我。 谢谢。

编辑:有老师和学生。 通过查看classes_users表,可以找到他们在任何给定班级中作为学生或老师的地位。 我要做的就是给用户一个用户,找到他是老师的班级,然后返回这些班级中的所有学生。

这是我的数据库架构:

-- -----------------------------------------------------
-- Table `kcptech`.`users`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `kcptech`.`users` (
`users_username` VARCHAR(63) NOT NULL ,
`password` VARCHAR(255) NULL DEFAULT NULL ,
`salt` VARCHAR(127) NULL DEFAULT NULL ,
`givenname` VARCHAR(96) NULL DEFAULT NULL ,
`familyname` VARCHAR(128) NULL DEFAULT NULL ,
`privileges` TINYINT NULL DEFAULT NULL ,
`studentassent` TINYINT(1) UNSIGNED NULL DEFAULT NULL ,
`parentconsent` TINYINT(1) UNSIGNED NULL DEFAULT NULL ,
`birthdate` DATE NULL DEFAULT NULL ,
`gender` VARCHAR(1) NULL DEFAULT NULL ,
`registration` TIMESTAMP NULL DEFAULT NULL ,
PRIMARY KEY (`users_username`) ,
UNIQUE INDEX `uname_UNIQUE` (`users_username` ASC) )
ENGINE = InnoDB;




-- -----------------------------------------------------
-- Table `kcptech`.`classes`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `kcptech`.`classes` (
`classes_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`course` VARCHAR(127) NULL ,
`period` VARCHAR(31) NULL DEFAULT '' ,
`organization` VARCHAR(127) NULL DEFAULT '' ,
PRIMARY KEY (`classes_id`) ,
UNIQUE INDEX `id_UNIQUE` (`classes_id` ASC) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `kcptech`.`classes_users`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `kcptech`.`classes_users` (
`classes_id` INT UNSIGNED NOT NULL ,
`users_username` VARCHAR(64) NOT NULL ,
`role` VARCHAR(12) NOT NULL ,
PRIMARY KEY (`classes_id`, `users_username`) ,
INDEX `fk_class_users__users_users_username` (`users_username` ASC) ,
INDEX `fk_class_users__class_class_id` (`classes_id` ASC) ,
CONSTRAINT `fk_class_users__users_users_username`
  FOREIGN KEY (`users_username` )
  REFERENCES `kcptech`.`users` (`users_username` )
  ON DELETE NO ACTION
  ON UPDATE NO ACTION,
CONSTRAINT `fk_class_users__class_class_id`
  FOREIGN KEY (`classes_id` )
  REFERENCES `kcptech`.`classes` (`classes_id` )
  ON DELETE NO ACTION
  ON UPDATE NO ACTION)
ENGINE = InnoDB;

第一个更好,假设(classes_id, users_username)是唯一的。

MySQL无法使用内部查询前导进行半联接( IN构造)。 因此, IN查询将始终将users用作主表,而对于JOIN查询,优化器可以选择主表。

如果(classes_id, users_username)不是唯一的,则查询在语义上不等效。 您需要将DISTINCT添加到联接查询中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM