вопрос множественного левого соединения - PullRequest
0 голосов
/ 17 марта 2012
$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. Если кто-то знает лучший способ сделать то, что я пытаюсь выполнить, или подскажет, как решить проблему, это будет с благодарностью!

Спасибо

Jeff

РЕДАКТИРОВАТЬ: чтобы добавить, ни один столбец с повторяющимися именами все по-другому.

1 Ответ

1 голос
/ 17 марта 2012

Для этой проблемы нет ни одной серебряной пули;Получение информации о родительской таблице, а также получение информации из нескольких дочерних таблиц с отношениями «один ко многим» всегда сложно.Но есть несколько техник, которые могут помочь.

Во-первых, вы на самом деле ничего не делаете с tblFinishedContracts, кроме как получаете из него количество записей;поэтому вместо написания COUNT(tblFinishedContracts.ID) и использования объединения вы можете использовать подзапрос: write (SELECT COUNT(1) FROM tblFinishedContracts WHERE Company_ID = tblCompanies.Company_ID).То же самое относится и к tblFinishedSubContracts, поэтому вы можете исключить и это объединение.(Кстати, устранение этих объединений также должно значительно улучшить вашу производительность, поскольку вам нужно будет только получить информацию о контрактах, которые принадлежат компаниям, которые фактически возвращаются.)

Это касается большинство проблемы.Соединения с users и cargo для получения генерального директора и предпочитаемого груза не должны вызывать никаких проблем.(Верно?)

Единственная оставшаяся трудность - это 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.Таким образом, в другом месте запроса вы можете заменить SUM(tblCTerminals.sellValue) на tblCompanies.totalCTerminalSellValue.

...