这个查询有什么问题?

时间:2011-02-08 22:50:21

标签: sql mysql

我正在尝试编写一个从四个表中选择的查询

  • campaignSentParent csp
  • campaignSentEmail cse
  • campaignSentFax csf
  • campaignSentSms css

每个cse,csf和css表都通过csp.id =(cse / csf / css)链接到csp表.parentId

csp表有一个名为campaignId的列,

我想要做的是最终看起来像这样的行:

| id | dateSent   | emailsSent | faxsSent | smssSent |  
| 1  | 2011-02-04 | 139        | 129      | 140      |  

但相反,我最终得到的行如下:

| 1  | 2011-02-03 | 2510340    | 2510340  | 2510340  |

这是我正在尝试的查询

SELECT csp.id id, csp.dateSent dateSent,  
       COUNT(cse.parentId) emailsSent,  
       COUNT(csf.parentId) faxsSent,  
       COUNT(css.parentId) smsSent  
FROM   campaignSentParent csp,  
       campaignSentEmail cse,  
       campaignSentFax csf,  
       campaignSentSms css  
WHERE  csp.campaignId = 1  
AND    csf.parentId = csp.id  
AND    cse.parentId = csp.id  
AND    css.parentId = csp.id;  

<小时/> 添加GROUP BY没有帮助,所以我发布了创建语句。

CSP

CREATE TABLE `campaignsentparent` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `campaignId` int(11) NOT NULL,
  `dateSent` datetime NOT NULL,
  `account` int(11) NOT NULL,
  `status` varchar(15) NOT NULL DEFAULT 'Creating',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1

cse / csf(结构相同,名称不同)

CREATE TABLE `campaignsentemail` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parentId` int(11) NOT NULL,
  `contactId` int(11) NOT NULL,
  `content` text,
  `subject` text,
  `status` varchar(15) DEFAULT 'Pending',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=140 DEFAULT CHARSET=latin1

CSS

CREATE TABLE `campaignsentsms` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parentId` int(11) NOT NULL,
  `contactId` int(11) NOT NULL,
  `content` text,
  `status` varchar(15) DEFAULT 'Pending',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=141 DEFAULT CHARSET=latin1

4 个答案:

答案 0 :(得分:3)

您需要单独汇总金额,而不是问题中所示。

SELECT csp.id, csp.dateSent dateSent,  
       e.email_count, f.fax_count, s.sms_count
  FROM campaignSentParent AS csp
  JOIN (SELECT cse.ParentId, COUNT(*) AS email_count
          FROM campaignSentEmail cse
         GROUP BY cse.ParentID) AS e ON e.parentID = csp.id
  JOIN (SELECT csf.ParentId, COUNT(*) AS fax_count
          FROM campaignSentFax csf
         GROUP BY csf.ParentID) AS f ON f.ParentID = csp.id
  JOIN (SELECT css.ParentID, COUNT(*) AS sms_count
          FROM campaignSentSms css
         GROUP BY css.ParentId) AS s ON s.ParentID = csp.id
 WHERE csp.campaignId = 1  

要做到这一点,你几乎必须使用JOIN表示法,如图所示。

根据优化程序的质量以及各种表的基数和可用索引,您可能会发现在每个具有csp.CampaignID = 1条件的子查询中包含与CampaignSentParent的连接是有效的,以限制子查询聚合的数据。


你可能会注意到你得到的结果数是2510340. 2510340的素数因子分解是2×2×3×5×7×43×139,你的预期答案是139,129和140.你可以得到3×43 = 129; 2×2×5×7 = 140;换句话说,原始查询生成三个从属表中所有行的笛卡尔积并计算产品,而不是分别计算每个从属表中的相关行。

答案 1 :(得分:0)

你最后错过了一个GROUP BY语句。我无法从您的示例中看出您希望将它们分组以实际为您提供代码。

答案 2 :(得分:0)

GROUP BY dateSent添加到查询的末尾。

答案 3 :(得分:0)

尝试添加group by子句。

SELECT csp.id id, csp.dateSent dateSent,  
       COUNT('cse.parentId') emailsSent,  
       COUNT('csf.parentId') faxsSent,  
       COUNT('css.parentId') smsSent  
FROM   campaignSentParent csp,  
       campaignSentEmail cse,  
       campaignSentFax csf,  
       campaignSentSms css  
WHERE  csp.campaignId = 1  
AND    csf.parentId = csp.id  
AND    cse.parentId = csp.id  
AND    css.parentId = csp.id
GROUP BY csp.id, csp.dateSent

使用聚合函数时,通常需要包含一个组。