从不同的表中获得总和和计数

时间:2015-03-06 22:25:01

标签: mysql report

我猜这太局部了,但我想办法让它更通用(这可能就是为什么我无法在Google上找到答案)。

我们有一个应用程序可以跟踪我们业务的联系人。可通过电话(Contact_Phone表)或电子邮件(Contact_Email)联系这些联系人(联系表)。如果通过电话联系用户,则代理会跟踪总秒数(Contact_Phone.totalSeconds)。通过我无法控制电子邮件联系人的业务逻辑被视为一秒钟。用户可能只通过电子邮件,电话或两者联系。

我正在尝试生成一份报告,说明我们花了多长时间联系每个用户,但我无法得到我期望的结果。

表:

CREATE  TABLE IF NOT EXISTS `Contact` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


CREATE  TABLE IF NOT EXISTS `Contact_Email` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `ContactId` INT NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `contact_email_contact_idx` (`ContactId` ASC) ,
  CONSTRAINT `contact_email_contact`
    FOREIGN KEY (`ContactId` )
    REFERENCES `Contact` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS `Contact_Phone` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `totalSeconds` INT NULL ,
  `ContactId` INT NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `Contact_Phone_contact_idx` (`ContactId` ASC) ,
  CONSTRAINT `Contact_Phone_contact`
    FOREIGN KEY (`ContactId` )
    REFERENCES `Contact` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

测试数据:

insert into Contact (id, name) values (1, 'Scott');
insert into Contact (id, name) values (2, 'Joe');

insert into Contact_Phone (totalSeconds, ContactId) values (10, 2);
insert into Contact_Phone (totalSeconds, ContactId) values (100, 2);

insert into Contact_Email (ContactId) values (1);
insert into Contact_Email (ContactId) values (1);
insert into Contact_Email (ContactId) values (2);

查询:

select 
name,
    (select sum(totalSeconds) from Contact_Phone where Contact_Phone.ContactId = Contact.id) 
    + 
    (select count(*) from Contact_Email where Contact_Email.ContactId = Contact.id)
from Contact;

预期结果:

Joe    111
Scott  2

实际结果:

Joe    111
Scott  null

由于

1 个答案:

答案 0 :(得分:1)

如何使用摘要和LEFT JOIN操作呢?

SELECT Contact.name,
       COALESCE(p.seconds,0) + COALESCE(e.seconds,0) seconds
  FROM Contact.Name
  LEFT JOIN (
              SELECT ContactID AS id,
                     SUM(totalSeconds) AS seconds
                FROM ContactPhone
               GROUP BY ContactID
             ) p  ON Contact.id = p.id
  LEFT JOIN (
              SELECT ContactID AS id,
                     COUNT(*) AS seconds
                FROM ContactEmail
               GROUP BY ContactID
             ) e  ON Contact.id = e.id

LEFT JOIN操作将保留结果行,其中一个或另一个“秒”计算为NULL。并且,COALESCE操作将阻止您的查询尝试对NULL值进行算术运算,从而产生NULL。