如何改进此SQL以避免其结果出现问题?

时间:2011-01-02 05:24:40

标签: mysql sql

我在尝试搜索方面遇到了一些问题。目前,这只会返回在maintenance_parts表中至少有一行的结果。我希望它返回结果,即使有0部分行。

我的第二个问题是,当您搜索车辆并且它应该返回多个结果(多个维护行)时,它将仅返回该车辆的1个结果。

一些背景信息 用户有2个字段要填写。字段是车辆和关键字。车辆区域允许基于品牌,型号,VIN,卡车号码(通常是2-3位数字或字母前缀后跟2位数字)以及属于卡车工作台的其他一些字段进行搜索。关键字用于搜索maintenance和maintenance_parts表中的大多数字段(例如工作描述,部件名称,部件号)。

maintenance_parts表可以为每个维护行包含0个,1个或更多行。卡车工作台每个维护行只包含1行。卡车可以有多个维护记录。

 "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"

1 个答案:

答案 0 :(得分:1)

您的代码在Maintenance和Maintenace_parts之间进行连接您需要做的第一件事就是将其转换为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...

执行此操作后,如果找不到匹配的行,您将获得maintenance_parts中每列的空值。看来你的代码可以正常使用,但要确保你的select和where子句MATCH函数能正常使用NULL

使用NULLS进行检查/审核的代码如下

 OR MATCH( P.part_num, P.part_desc, P.part_ref) AGAINST( '$keywords' )

第二个问题似乎是您按 maintenance_id 而不是 truck_id 进行分组。尝试更改GROUP BY字段,它应该解决您的第二个问题

下面修改了查询

    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"
相关问题