Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL计数(*)不计算结果行_Mysql_Sql - Fatal编程技术网

MySQL计数(*)不计算结果行

MySQL计数(*)不计算结果行,mysql,sql,Mysql,Sql,实现订阅模型的m:n关系的简化模式: CREATE TABLE c ( id INT(11) PRIMARY KEY AUTO_INCREMENT, name VARCHAR(32) ) ENGINE=MyISAM CHARACTER SET=UTF8; CREATE TABLE t ( id INT(11) PRIMARY KEY AUTO_INCREMENT, name VARCHAR(32) ) ENGINE=MyISAM CHARACTER SET=UTF8; CRE

实现订阅模型的m:n关系的简化模式:

CREATE TABLE c (
  id INT(11) PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(32)
) ENGINE=MyISAM CHARACTER SET=UTF8;

CREATE TABLE t (
  id INT(11) PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(32)
) ENGINE=MyISAM CHARACTER SET=UTF8;

CREATE TABLE c2t (
  id INT(11) PRIMARY KEY AUTO_INCREMENT,
  cid INT(11) NOT NULL,
  tid INT(11) NOT NULL,
  dateStart DATE NULL,
  dateEnd DATE NULL
) ENGINE=MyISAM CHARACTER SET=UTF8;

INSERT INTO c (name) VALUES ('mike'),('carl'),('suzy');

INSERT INTO t (name) VALUES ('plan1'),('plan2'),('plan3'),('plan4');

INSERT INTO c2t (cid, tid, dateStart, dateEnd) VALUES
  (1, 1, '2014-01-01', '2014-07-31'),
  (1, 2, '2014-08-01', '2015-07-31'),
  (1, 1, '2015-08-01', null),
  (1, 3, '2015-09-01', null),

  (2, 1, '2014-01-01', '2015-07-31'),
  (2, 2, '2015-08-01', '2015-09-30'),
  (2, 3, '2015-09-30', null),

  (3, 1, '2014-01-01', '2014-12-31'),
  (3, 2, '2014-01-01', '2014-12-31'),
  (3, 3, '2015-01-01', '2015-10-31'),
  (3, 4, '2015-01-01', '2015-10-31');
我开发了一个查询来查找拥有t的活动订阅的c:

SELECT c.*
FROM c
LEFT JOIN c2t ON c.id = c2t.cid
  AND NOW() BETWEEN COALESCE(dateStart, '0000-00-00')
    AND COALESCE(dateEnd, DATE_ADD(NOW(), INTERVAL 1 DAY))
GROUP BY c2t.cid
HAVING COUNT(c2t.id) > 0;
结果如预期:

id  name
1   mike
2   carl
当我试图计算结果行时,问题就出现了。查询几乎相同,我刚刚输入了一个计数(*):

结果:

`COUNT(*)`
2
1

预期结果将是包含找到的行数(2)的单行。我只能假设小组正在干预,但不知道如何解决。非常欢迎解释。

用子查询包装所有内容,并在外部查询中使用
COUNT

SELECT COUNT(*)
FROM (
  SELECT c.*
  FROM c
  LEFT JOIN c2t ON c.id = c2t.cid
    AND NOW() BETWEEN COALESCE(dateStart, '0000-00-00')
    AND COALESCE(dateEnd, DATE_ADD(NOW(), INTERVAL 1 DAY))
  GROUP BY c2t.cid
  HAVING COUNT(c2t.id) > 0
) AS sub

如果您只想返回具有活动订阅的c的数量,那么您可以简化查询,如下所示:

SELECT COUNT(DISTINCT c.id) AS cnt
FROM c
INNER JOIN c2t ON c.id = c2t.cid
  AND NOW() BETWEEN COALESCE(dateStart, '0000-00-00')
    AND COALESCE(dateEnd, DATE_ADD(NOW(), INTERVAL 1 DAY))
因此,
内部连接
被用来代替
左连接
:不需要返回在
c2t
中没有匹配项的c,因为它们不会有任何活动订阅

此外,不需要按分组:查询只返回一行c的数目


最后,
DISTINCT
必须在
COUNT
中使用,以避免重复的
c.id
值多次计数。

只是一个改进,而不是使用COUNT(*)尝试在该表中使用一个键,例如:COUNT(主键)将提高您的查询性能,尤其是在使用innodb时。@csf包装的SELECT会从子查询表中的索引中受益吗?@Willyde Check查询优化器(至少在SQL Server世界中)足够聪明,可以在
COUNT(1)/COUNT(*)/COUNT(pk)
SELECT COUNT(DISTINCT c.id) AS cnt
FROM c
INNER JOIN c2t ON c.id = c2t.cid
  AND NOW() BETWEEN COALESCE(dateStart, '0000-00-00')
    AND COALESCE(dateEnd, DATE_ADD(NOW(), INTERVAL 1 DAY))