【问题标题】:How can I improve this SQL to avoid several problems with its results?如何改进此 SQL 以避免其结果出现一些问题?
【发布时间】:2011-06-02 09:54:40
【问题描述】:

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

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

一些背景信息: 用户有 2 个字段要填写。这些字段是车辆和关键字。车辆字段旨在允许根据品牌、型号、VIN、卡车号码(通常是 2 - 3 位数字或字母前缀后跟 2 位数字)以及属于卡车表的一些其他字段进行搜索。关键字用于搜索维护和维护零件表中的大多数字段(例如工作描述、零件名称、零件编号)。

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"

【问题讨论】:

标签: mysql sql


【解决方案1】:

您的代码在 Maintenance 和 Maintenace_parts 之间执行 JOIN 您需要做的第一件事是将其转换为 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' )

第二个问题似乎是您按 ma​​intenance_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"

【讨论】:

  • 我得到:#1054 - 'on Clause' 中的未知列 'M.maintenance_id'
  • 这是一个惊喜,因为原始代码发现了它。我已经编辑了答案以转换为对所有表使用 JOIN 方法,MYSQL 中可能有些东西不允许您混合方法。试试看……
  • 另外,当您更改分组依据时,select 子句中的字段maintenance_id 必须替换为TRUCK_ID。你为什么还要使用 GROUP BY,看来你不需要它......
  • 我认为有一次我需要 GROUP BY,但改变了一堆东西,只是忘了摆脱它。
  • 更正,我确实需要它。这样我就没有为每个返回的 maintenance_part 保留一行。我需要搜索零件行,但我只需要返回卡车和维护信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 2012-03-20
  • 2011-08-15
  • 1970-01-01
  • 1970-01-01
  • 2015-03-02
  • 1970-01-01
相关资源
最近更新 更多