Hello @johnny,
Me again… sorry for the long post, it is important although!
I invite you so we can think together about the usage of the where clause in setRelation, take your seat…
If the where statement in the setRelation method (4th parameter) corresponds to the joined table, why it does not belong to the join statement itself and is applied to the whole query, after the join operation is performed? Let me exemplify using your on GC example db:
$crud->setTable('customers')
->setSubject('Customer', 'Customers')
->displayAs('customerName', 'Name')
->displayAs('contactLastName', 'Last Name')
->setRelation('salesRepEmployeeNumber', 'employees', 'lastName', 'officeCode > 0');
The query above produces the following SQL (MySQL DBMS), except that I’ve removed the pagination (LIMIT and OFFSET):
SELECT `customers`.`customerNumber` AS `customerNumber`,
`customers`.`customerName` AS `customerName`,
`customers`.`contactLastName` AS `contactLastName`,
`customers`.`contactFirstName` AS `contactFirstName`,
`customers`.`phone` AS `phone`,
`customers`.`addressLine1` AS `addressLine1`,
`customers`.`addressLine2` AS `addressLine2`,
`customers`.`city` AS `city`,
`customers`.`state` AS `state`,
`customers`.`postalCode` AS `postalCode`,
`customers`.`country` AS `country`,
`customers`.`salesRepEmployeeNumber` AS `salesRepEmployeeNumber`,
`customers`.`creditLimit` AS `creditLimit`,
`customers`.`updatedBy` AS `updatedBy`
FROM `customers`
LEFT JOIN `employees` AS `e` ON `customers`.`salesRepEmployeeNumber` = `e`.`employeeNumber`
WHERE officeCode > 0;
Notice that the where clause in being added globally to the query, after the join. And, in this case, it even reduces the query results even-though all officeCode
on table employees
are positive and none of them is NULL
. If used properly, this where clause should return the “correct” number of results (as if it was no where clause, please test check yourself the number of results returned in each of these 3 queries):
SELECT `customers`.`customerNumber` AS `customerNumber`,
`customers`.`customerName` AS `customerName`,
`customers`.`contactLastName` AS `contactLastName`,
`customers`.`contactFirstName` AS `contactFirstName`,
`customers`.`phone` AS `phone`,
`customers`.`addressLine1` AS `addressLine1`,
`customers`.`addressLine2` AS `addressLine2`,
`customers`.`city` AS `city`,
`customers`.`state` AS `state`,
`customers`.`postalCode` AS `postalCode`,
`customers`.`country` AS `country`,
`customers`.`salesRepEmployeeNumber` AS `salesRepEmployeeNumber`,
`customers`.`creditLimit` AS `creditLimit`,
`customers`.`updatedBy` AS `updatedBy`
FROM `customers`
LEFT JOIN `employees` AS `e` ON `customers`.`salesRepEmployeeNumber` = `e`.`employeeNumber` AND officeCode > 0;
The result above is equal to the one below (without where):
SELECT `customers`.`customerNumber` AS `customerNumber`,
`customers`.`customerName` AS `customerName`,
`customers`.`contactLastName` AS `contactLastName`,
`customers`.`contactFirstName` AS `contactFirstName`,
`customers`.`phone` AS `phone`,
`customers`.`addressLine1` AS `addressLine1`,
`customers`.`addressLine2` AS `addressLine2`,
`customers`.`city` AS `city`,
`customers`.`state` AS `state`,
`customers`.`postalCode` AS `postalCode`,
`customers`.`country` AS `country`,
`customers`.`salesRepEmployeeNumber` AS `salesRepEmployeeNumber`,
`customers`.`creditLimit` AS `creditLimit`,
`customers`.`updatedBy` AS `updatedBy`
FROM `customers`
LEFT JOIN `employees` AS `e` ON `customers`.`salesRepEmployeeNumber` = `e`.`employeeNumber` ;
Also, using the where clause like we are using right now imposes another issue: where clause is ambiguous. Mainly when using two where clauses on different setRelation
calls. To exemplify I will add a virtual column to your customers
table:
ALTER TABLE customers ADD COLUMN updatedBy INT GENERATED ALWAYS AS (salesRepEmployeeNumber) VIRTUAL;
$crud->setTable('customers')
->setSubject('Customer', 'Customers')
->displayAs('customerName', 'Name')
->displayAs('contactLastName', 'Last Name')
->setRelation('salesRepEmployeeNumber', 'employees', 'lastName', 'officeCode > 0')
->setRelation('updatedBy', 'employees', 'firstName', 'officeCode > 0');
Unfortunately, the php code above will trigger a Internal Server Error because of SQL Error (1052): Column ‘officeCode’ in where clause is ambiguous . This is the resulting query:
SELECT `customers`.`customerNumber` AS `customerNumber`,
`customers`.`customerName` AS `customerName`,
`customers`.`contactLastName` AS `contactLastName`,
`customers`.`contactFirstName` AS `contactFirstName`,
`customers`.`phone` AS `phone`,
`customers`.`addressLine1` AS `addressLine1`,
`customers`.`addressLine2` AS `addressLine2`,
`customers`.`city` AS `city`,
`customers`.`state` AS `state`,
`customers`.`postalCode` AS `postalCode`,
`customers`.`country` AS `country`,
`customers`.`salesRepEmployeeNumber` AS `salesRepEmployeeNumber`,
`customers`.`creditLimit` AS `creditLimit`,
`customers`.`updatedBy` AS `updatedBy`
FROM `customers`
LEFT JOIN `employees` AS `e` ON `customers`.`salesRepEmployeeNumber` = `e`.`employeeNumber`
LEFT JOIN `employees` AS `e__updatedBy` ON `customers`.`updatedBy` = `e__updatedBy`.`employeeNumber`
WHERE officeCode > 0
AND officeCode > 0
LIMIT 10
OFFSET 0;
Notice the repeated where clause. I think the correct query should be:
SELECT `customers`.`customerNumber` AS `customerNumber`,
`customers`.`customerName` AS `customerName`,
`customers`.`contactLastName` AS `contactLastName`,
`customers`.`contactFirstName` AS `contactFirstName`,
`customers`.`phone` AS `phone`,
`customers`.`addressLine1` AS `addressLine1`,
`customers`.`addressLine2` AS `addressLine2`,
`customers`.`city` AS `city`,
`customers`.`state` AS `state`,
`customers`.`postalCode` AS `postalCode`,
`customers`.`country` AS `country`,
`customers`.`salesRepEmployeeNumber` AS `salesRepEmployeeNumber`,
`customers`.`creditLimit` AS `creditLimit`,
`customers`.`updatedBy` AS `updatedBy`
FROM `customers`
LEFT JOIN `employees` AS `e` ON `customers`.`salesRepEmployeeNumber` = `e`.`employeeNumber` AND `e`.`officeCode` > 0
LEFT JOIN `employees` AS `e__updatedBy` ON `customers`.`updatedBy` = `e__updatedBy`.`employeeNumber` AND `e__updatedBy`.`officeCode` > 0
LIMIT 10
OFFSET 0;
Let me know what do you think about this…
Best regards!