有没有办法在MySQL中只显示一个WHERE子句?

我有一些课程,学生可以参加。 有一个用户表(usuarios),一个课程(cursos)表和第三个表格显示每个学生的注册(cursosUsuarios),如下所示:

CREATE TABLE usuarios( userID int unsigned not null auto_increment primary key, userName char(50) null, )ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE cursos ( cursoID int unsigned not null auto_increment primary key, nombreCurso char(100) not null, estadoCurso char(50) not null, )ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE cursosUsuarios ( cursosUsuariosID int unsigned not null auto_increment primary key, userID int not null, cursoID int not null, userHabilitado int(1) not null DEFAULT '0', )ENGINE=InnoDB DEFAULT CHARSET=utf8; 

每个用户都可以在每个课程中注册,但是直到被pipe理员“启用”,才能访问该课程。 启用意味着“userHabilitado”字段是“1”而不是默认的“0”。

现在,我试图在用户个人资料中显示所有可用课程的列表,以便pipe理员可以看到用户已注册了哪些课程,并在“userHabilitado”字段中将“0”更改为“1”。

这是我的查询:

 SELECT cursos.cursoID AS idcurso, cursos.estadoCurso, cursosUsuarios.userHabilitado AS 'ok', GROUP_CONCAT(cursosUsuarios.userID SEPARATOR ',') AS 'usuarios' FROM cursos LEFT JOIN cursosUsuarios ON cursos.cursoID = cursosUsuarios.cursoID LEFT JOIN usuarios ON cursosUsuarios.userID = usuarios.userID WHERE cursos.estadoCurso='abierto' GROUP BY cursos.cursoID; 

这是我得到的结果:

在这里输入图像描述

现在,我需要显示所有开放课程(estadoCurso字段设置为“abierto”)的课程,我没有添加一个WHERE子句来过滤用户的结果。

我所做的就是从URL中获取用户标识,然后展开“usuarios”字段来查找我正在查找的用户,如下所示:

  echo '<div class="checkbox">'; while ($curso=mysqli_fetch_assoc($buscarCurso)) { $usuario = $_GET['userID']; $usuarios = explode(',', $curso['usuarios']); ?> <input type="checkbox" <?php if (in_array($usuario, $usuarios)) {echo 'checked';}?> name="cursoID[]" value="<?php echo $curso['idcurso'];?>"> <?php echo '<b>'.$curso['nombreCurso'].'</b> ';?> <?php echo 'Id. curso: '.$curso['idcurso'].' <b>Estado usuario:</b> <input type="text" name="ok['.$curso['idcurso'].']" value ="'.$curso['ok'].'">';?> 

因此,如果用户标识位于$ usuarios数组中,则checkbox将被选中,因为这意味着用户已注册。

我的问题是如何在该列表中显示userHabilitado字段。 在上面的图像中,用户70被注册了三个课程:courseID 15,16和18.在每种情况下,userHabilitado字段被设置为“1”,但是结果在那里是不正确的。

我想用cursosUsuarios.userHabilitado AS 'ok'replace为: cursosUsuarios.userHabilitado WHERE usuarios.userID = 70 ,但是在该字段中。

在MySQL中可能吗?

在MySQL 5.7之前,默认是允许非FULL group by 。 这意味着你可以使用其他非聚合列(使用summaxcountgroup_concat等集合函数)的group_concat (我们称它们为“ NON AGGS ),就像你的前3列没有显示group by子句的所有部分一样。 它允许它,但结果通常是这样的:

  • 它的工作很好,因为你知道你的数据,并试图实现一个独特的

  • 它成了可怕的,因为它是一个snafu

在5.7之前, ONLY_FULL_GROUP_BY存在,但是默认情况下它被closures。

所以在MySQL 5.7中, ONLY_FULL_GROUP_BY默认为ON。 因此,如果您尝试使用group by,但并不是 group by子句中的所有 NON AGGS ,那么您将得到一个错误。

考虑下面的5.6中的以下问题:

 create table thing ( col1 int not null, col2 int not null, age int not null ); insert thing(col1,col2,age) values (1,2,10), (1,3,20), (2,3,20), (2,2,10); select col1,col2,max(age) from thing group by col1; +------+------+----------+ | col1 | col2 | max(age) | +------+------+----------+ | 1 | 2 | 20 | | 2 | 3 | 20 | +------+------+----------+ 

上面发生的事情并不是所有的NON AGGS都在group by 。 它通过col1返回最大值(年龄)。 但是由于col2并不在group by ,所以它使用了Cluster Index或Physical Ordering,并且可能会(无意中错误地)带来了col2的错误值。 取决于你的意图或知道你的数据,甚至关心。 发动机不在乎; 也许你呢。

为了避免这些常见错误或无意的数据返回,默认情况下,MySQL 5.7打开ONLY_FULL_GROUP_BY

在你的情况,错误的行正在弥补你的结果可能是列2和3。

请参阅手册页,标题为MySQL处理GROUP BY 。


例2

 -- drop table if exists person; create table person ( id int auto_increment primary key, firstName varchar(100) not null, lastName varchar(100) not null ); -- drop table if exists fruitConsumed; create table fruitConsumed ( id int auto_increment primary key, theDate date not null, fruitId int not null, -- does not really matter. Say, 1=apple, 2=orange from some other table personId int not null, qty int not null ); -- truncate table person; insert person (firstName,lastName) values ('Dirk','Peters'), ('Dirk','Smith'), ('Jane','Billings'); -- truncate table fruitConsumed; insert fruitConsumed (theDate,fruitId,personId,qty) values ('2016-10-31',1,1,2), ('2016-10-31',2,1,5), ('2016-10-31',2,2,12), ('2016-11-02',2,2,3); 

查询:

 select p.firstName,p.lastName,sum(fc.qty) from person p join fruitConsumed fc on fc.personId=p.id group by p.firstName,p.lastName; +-----------+----------+-------------+ | firstName | lastName | sum(fc.qty) | +-----------+----------+-------------+ | Dirk | Peters | 7 | | Dirk | Smith | 15 | +-----------+----------+-------------+ 

不pipeONLY_FULL_GROUP_BY的设置如何,以上的工作在MySQL 5.6和5.7上都ONLY_FULL_GROUP_BY

现在考虑

 select p.firstName,p.lastName,sum(fc.qty) from person p join fruitConsumed fc on fc.personId=p.id group by p.firstName; +-----------+----------+-------------+ | firstName | lastName | sum(fc.qty) | +-----------+----------+-------------+ | Dirk | Peters | 22 | +-----------+----------+-------------+ 

以上情况在MySQL 5.6中通常是可以接受的,没有启用ONLY_FULL_GROUP_BY并且在启用了ONLY_FULL_GROUP_BY (错误1055)的情况下在5.7上失败。 以上输出基本上是乱码。 但是下面有些解释:

我们知道德克,德克,只有一个德克,是唯一一个能够在内部join的人。 有2个Dirks。 但是由于group by p.firstName ,我们只剩下一个Dirk。 我们需要一个lastName 。 因为不符合
SQL标准,MySQL可以允许这与ONLY_FULL_GROUP_BYclosures。 所以它只是select任何旧的姓氏。 那么,它发现的第一个,这是在caching或物理sorting。

和彼得一起去了。 果数总和适用于所有的Dirks。

所以如果你这样写代码,那么不符合的ONLY_FULL_GROUP_BY给你一个乱码。

如前所述,MySQL 5.7默认不允许这样做。 但是,如果您select的话,它可以旧的方式调整。

强烈build议您修复查询并将ONLY_FULL_GROUP_BY为启用状态。

您的查询是针对sql标准的,因为您在select列表中既不在group by子句中的字段也不是聚合函数的主题。

具体而言,您在select列表中有cursosUsuarios.userHabilitado AS 'ok'字段,但您只能在cursos.cursoID字段上进行cursos.cursoID 。 这意味着,如果你注册了一个没有注册的学生在一门课程中,他们都将显示为已注册或未注册。 扩展你的group by子句以符合sql标准并获得预期的结果:

 ...GROUP BY cursos.cursoID, cursos.estadoCurso, cursosUsuarios.userHabilitado;