MySQL COUNT(*)不计算结果行

时间:2015-11-25 16:06:11

标签: mysql sql

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

function clonage(elem) {
this.c = "#"+elem;
$(c).draggable({revert: 'invalid',helper: 'clone',cursor: 'move',tolerance: 'fit' });
$(".droppable").droppable({
    drop: function(e, ui) {
        x = ui.helper.clone(false);
        if(!inArray(elements,x[0].id)){
            if(!(ui.draggable[0].className).indexOf('tableRonde')){
                x[0].id = 'tableRonde'+nbtr; nbtr++; rs = nbtr-1;
                param= 'tableRonde'+rs;tname = ntr+rs;
                x.attr('name',tname);
                x.html(tname +' <a href="#" onClick="openPopup('+param+')">Editer</a>');
                x[0].className = 'tableRonde1';
            }else if (!(ui.draggable[0].className).indexOf('table')){
                x[0].id = 'table'+nbt; nbt++;rs = nbt-1;
                param= 'table'+rs;tname = nt+rs;
                x.attr('name',tname);
                x.html(tname +' <a href="#" onClick="openPopup('+param+')">Editer</a>');
                x[0].className = 'table1';
            }else if (!(ui.draggable[0].className).indexOf('zone')){

                x[0].id = 'zone'+nbz; nbz++;rs = nbz-1;
                param= 'zone'+rs;tname = nz+rs;
                x.attr('name',tname);
                x.html(tname +' <a href="#" onClick="openPopup('+param+')" >Editer</a>');
                x[0].className = 'zone1';

            }else if (!(ui.draggable[0].className).indexOf('plan')){
                x[0].id = 'plan'+nbp; nbp++;rs = nbp-1;
                param= 'plan'+rs;tname = np+rs;
                x.attr('name',tname);
                x.html(tname +' <a href="#" onClick="openPopup('+param+')">Editer</a>');
                x[0].className = 'plan1';
            }
            elements.push(x[0].id);
        };
        x.draggable({
            tolerance: 'intersect',
            helper: 'original',
            containment: 'parent',
            tolerance: 'fit',
            revert: 'invalid'                
        });
        x.find('.ui-resizable-handle').remove();
        ui.helper.remove();
        x.resizable({
            minHeight: 60,
            minWidth: 50,
            containment: 'parent'
        });
        F = x[0].id;
        x.attr('width','0px');
        x.attr('heigth','0px');
        x.appendTo(".surface");
    },
    accept:function(){
        fla = true;
        for(i in elements){
            if(elements[i]!=F && elements[i]!="surface" && elements[i]!="menu" && elements[i].indexOf("zone") && F.indexOf("zone"))
            {    
                if(collisionDivDetect(F,elements[i])){
                    fla = false;
                }   
                if(collisionDivDetect(elements[i],F)){
                   fla = false;
                }
            }  
        } 
        return fla;
    }

我已经开发了一个查询来查找有效订阅t的人:

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');

按预期结果:

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;

当我尝试计算结果行时出现问题。查询几乎完全相同,我刚刚放入COUNT(*):

id  name
1   mike
2   carl

结果:

SELECT COUNT(*)
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;

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

2 个答案:

答案 0 :(得分:1)

用子查询包装所有内容并在外部查询中使用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

答案 1 :(得分:1)

如果您想要返回的唯一内容是拥有有效订阅的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))

因此,使用INNER JOIN代替LEFT JOIN:无法在c2t中返回没有匹配的c,因为这些不会有任何匹配有效订阅。

此外,不需要GROUP BY:查询只返回一行,其中包含c的数量。

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