Reputation: 10226
I am having some problems with trying to search. Currently this will only return results that have at least 1 row in the maintenance_parts table. I would like it to return results even if there are 0 parts rows.
My second problem is that when you search for a vehicle and it should return multiple results (multiple maintenance rows) it will only return 1 result for that vehicle.
Some Background Info: The user has 2 fields to fill out. The fields are vehicle and keywords. The vehicle field is meant to allow searching based on the make, model, VIN, truck number (often is 2 - 3 digits or a letter prefix followed by 2 digits), and a few other fields that belong to the truck table. The keywords are meant to search most fields in the maintenance and maintenance_parts tables (things like the description of the work, parts name, parts number).
The maintenance_parts table can contain 0, 1, or more rows for each maintenance row. The truck table contains exactly 1 row for every maintenance row. A truck can have multiple maintenance records.
"SELECT M.maintenance_id, M.some_id, M.type_code, M.service_date, M.mileage, M.mg_id, M.mg_type, M.comments, M.work_done,
MATCH( M.comments, M.work_done) AGAINST( '$keywords' ) +
MATCH( P.part_num, P.part_desc, P.part_ref) AGAINST( '$keywords' ) +
MATCH( T.truck_number, T.make, T.model, T.engine, T.vin_number, T.transmission_number, T.comments) AGAINST( '$vehicle' )
AS score
FROM maintenance M, maintenance_parts P, truck T
WHERE M.maintenance_id = P.maintenance_id
AND M.some_id = T.truck_id
AND M.type_code = 'truck'
AND (
(MATCH( T.truck_number, T.make, T.model, T.engine, T.vin_number, T.transmission_number, T.comments) AGAINST( '$vehicle' )
OR T.truck_number LIKE '%$vehicle%')
OR MATCH( P.part_num, P.part_desc, P.part_ref) AGAINST( '$keywords' )
OR MATCH( M.comments, M.work_done) AGAINST( '$keywords' )
)
AND M.status = 'A' GROUP BY maintenance_id ORDER BY score DESC, maintenance_id DESC LIMIT 0, $limit"
Upvotes: 0
Views: 80
Reputation: 15105
Your code does a JOIN between Maintenance and Maintenace_parts The first thing you will need to do is convert this to a LEFT JOIN
FROM maintenance M
JOIN truck T ON t.truck_id=M.some_id
LEFT JOIN maintenance_parts P ON M.maintenance_id = P.maintenance_id
WHERE...
After you do this, you will get null values for every column in maintenance_parts if a matching row is not found. It appears your code will be OK with this, but make sure your select and where clause MATCH function properly work with NULLs
Code to check/review that is works properly with NULLS is the following
OR MATCH( P.part_num, P.part_desc, P.part_ref) AGAINST( '$keywords' )
The second problems appears to be that you are grouping by maintenance_id instead of truck_id. Try changing the GROUP BY field, it should solve your second issue
Revised query below
SELECT T.TRUCK_ID,M.maintenance_id, M.some_id, M.type_code, M.service_date,
M.mileage, M.mg_id, M.mg_type, M.comments, M.work_done,
MATCH( M.comments, M.work_done) AGAINST( '$keywords' ) +
IfNull(P.PartScore,0) +
MATCH( T.truck_number, T.make, T.model, T.engine, T.vin_number, T.transmission_number, T.comments) AGAINST( '$vehicle' )
AS score
FROM maintenance M,
JOIN
(SELECT Truck_id,truck_number, make, model, engine, vin_number, transmission_number,comments FROM Truck
UNION
SELECT Truck_id,truck_number, make, model, engine, vin_number, transmission_number,comments FROM Trailer
)
T
ON M.some_id=T.Truck_id
LEFT JOIN
(SELECT maintenance_id,SUM(MATCH( P.part_num, P.part_desc, P.part_ref) AGAINST( '$keywords' )) AS PartScore
FROM maintenance_parts
GROUP BY maintenance_id ) P
P ON M.maintenance_id = P.maintenance_id
WHERE M.type_code = 'truck'
AND (
(MATCH( T.truck_number, T.make, T.model, T.engine, T.vin_number, T.transmission_number, T.comments) AGAINST( '$vehicle' )
OR T.truck_number LIKE '%$vehicle%')
OR MATCH( P.part_num, P.part_desc, P.part_ref) AGAINST( '$keywords' )
OR MATCH( M.comments, M.work_done) AGAINST( '$keywords' )
)
AND M.status = 'A'
ORDER BY score DESC, maintenance_id DESC
LIMIT 0, $limit"
Upvotes: 1