2012-03-17 89 views
0
$sth = $db->prepare("SELECT tblCompanies.*, users.Username, cargo.Name, (tblCompanies.Money + SUM(tblCTerminals.sellValue)) as assets, (COUNT(tblFinishedContracts.ID) + COUNT(tblFinishedSubContracts.ID)) as completed FROM ((((tblCompanies LEFT JOIN users ON tblCompanies.CompanyCEO = users.ID) LEFT JOIN cargo ON (tblCompanies.PreferredCargo = cargo.Cargo_ID)) LEFT JOIN tblCTerminals ON (tblCompanies.Company_ID = tblCTerminals.companyID)) LEFT JOIN tblFinishedContracts ON (tblCompanies.Company_ID = tblFinishedContracts.companyID)) LEFT JOIN tblFinishedSubContracts ON (tblCompanies.Company_ID = tblFinishedSubContracts.companyID) WHERE (users.Username LIKE :info || tblCompanies.CompanyName LIKE :info2 || CONCAT('$',FORMAT((tblCompanies.Money + SUM(tblCTerminals.sellValue)),2)) LIKE :info3 || CONCAT('$',FORMAT(tblCompanies.Money,2)) LIKE :info4 || cargo.Name LIKE :info5 || users.pLevel LIKE :info6 || CONCAT('$',FORMAT((users.Cash_In_Bank + users.Cash_In_Hand),2)) LIKE :info7)"); 

$sth->bindValue(':info', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR); 
$sth->bindValue(':info2', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR); 
$sth->bindValue(':info3', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR); 
$sth->bindValue(':info4', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR); 
$sth->bindValue(':info5', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR); 
$sth->bindValue(':info6', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR); 
$sth->bindValue(':info7', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR); 

好了,所以现在我的推理这个烂摊子:多个左连接的问题

我使用jQuery Datatables插件,当它的请求到服务器发送查询。它期望返回结果,搜索查询中有多少个结果以及多少个结果。有了这个查询,我可以返回结果。

但是在COUNT(tblFinishedContracts.ID)上,它抓取表8次。因此,例如,而不是返回的8正确的金额它返回的112

计数当我这样做:

SELECT COUNT(tblFinishedContracts.ID) 
FROM tblCompanies 
LEFT JOIN tblFinishedContract 
    ON (tblCompanies.Company_ID = tblFinishedContracts.ID)  
WHERE tblCompanies.Company_ID = 11 

它的工作原理,它返回8.如果有人知道这样做的更好的方法是什么我试图完成或可以告诉我如何解决这个问题,这将不胜感激!

感谢,

杰夫

编辑:添加,没有列重名的一切都不同了。

回答

1

这个问题没有单一的银弹;获取关于父表的信息,同时也从多个子表获取具有一对多关系的信息总是很棘手。但是有一些技巧可以提供帮助。

首先,您实际上没有对tblFinishedContracts做任何事情,除非从中获得记录数;所以不要编写COUNT(tblFinishedContracts.ID)并使用联接,您可以使用子查询:write (SELECT COUNT(1) FROM tblFinishedContracts WHERE Company_ID = tblCompanies.Company_ID)。同样的事情适用于tblFinishedSubContracts,所以您可以消除该连接。 (顺便说一句,消除这些连接也会显着提高您的性能,因为您只需检索属于实际退回公司的合同的信息。)

这需要照顾大多数问题。加入userscargo以获得首席执行官和首选货物不应造成任何问题。 (对吧?)

剩下的唯一难点是tblCTerminals,因为SUM(tblCTerminals.sellValue)字段出现在字段列表和WHERE子句中。没有真正有说服力的方法来处理它。一种选择是使用上述子查询方法,并使用子查询的两个副本。另一种方法是将FROM tblCompanies替换为FROM (SELECT tblCompanies.*, COALESCE(SUM(tblCTerminals.sellValue), 0) AS totalCTerminalSellValue FROM tblCompanies LEFT JOIN tblCTerminals ON tblCTerminals.Company_ID = tblCompanies.Company_ID GROUP BY tblCompanies.Company_ID) AS tblCompanies,其实质上创建了一个tblCompanies的临时副本,并增加了一个名为totalCTerminalSellValue的新字段。因此,在查询的其他地方,您可以用tblCompanies.totalCTerminalSellValue替换SUM(tblCTerminals.sellValue)

+0

好吧,这就是我现在的,我得到一个错误,说附近检查正确的语法“SELECT 1 FROM tblFinishedSubContracts WHERE companyID = tblCompanies.Company_ID)'”:'SELECT COUNT(SELECT 1 FROM tblFinishedSubContracts WHERE (tblCompanies LEFT JOIN cargo ON(tblCompanies.PreferredCargo = cargo.Cargo_ID))LEFT JOIN tblCTerminals ON(tblCompanies.Company_ID = tblCTerminals.companyID))LEFT JOIN用户ON tblCompanies.CompanyCEO = users.ID )WHERE tblCompanies.Company_ID = 7'不太确定它有什么问题。 – jefffan24 2012-03-17 20:05:41

+0

@ jefffan24:我的错:我遗漏了一对括号。 'COUNT(SELECT ...)'应该是COUNT((SELECT ...))'(一对属于'COUNT',分隔它的参数;另一个属于子查询,标记为这样)。我纠正了我的答案。 – ruakh 2012-03-17 20:14:47

+0

新问题:子查询返回多于1行...可以计算处理该类型的子查询吗? – jefffan24 2012-03-17 20:18:04