格式错误的sql查询,需要清理

时间:2011-04-27 19:50:48

标签: mysql

嘿嘿,我收到了一个可怕的查询,想知道是否有人可以看看它,让我知道如何清理它的任何建议。它有效,但是当有太多记录存在时,它运行缓慢。它只涉及两个表,但查询基本上从problem_nodes表中的行中获取值,并将它们转换为最终结果的列。

SELECT *
FROM   (SELECT urgency,
               name,
               phone,
               location,
               department,
               cc,
               status,
               case_manager,
               ip,
               case_manager_ei d,
               id_problem,
               id_problem_type,
               eid_author,
               title,
               body,
               date_created,
               date_modified
        FROM   problems AS main
               INNER JOIN (SELECT id_problem as t_urgency_id_problem,
                                  node_value AS urgency
                           FROM   problem_nodes
                           WHERE  node_name = "urgency")t_urgency
                 ON t_urgency.t_urgency_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_name_id_problem,
                                  node_value AS name
                           FROM   problem_nodes
                           WHERE  node_name = "name")t_name
                 ON t_name.t_name_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_phone_id_problem,
                                  node_value AS phone
                           FROM   problem_nodes
                           WHERE  node_name = "phone")t_phone
                 ON t_phone.t_phone_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_location_id_problem,
                                  node_value AS location
                           FROM   problem_nodes
                           WHERE  node_name = "location")t_location
                 ON t_location.t_location_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_department_id_problem,
                                  node_value AS department
                           FROM   problem_nodes
                           WHERE  node_name = "department")t_department
                 ON t_department.t_department_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_cc_id_problem,
                                  node_value AS cc
                           FROM   problem_nodes
                           WHERE  node_name = "cc")t_cc
                 ON t_cc.t_cc_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_status_id_problem,
                                  node_value AS status
                           FROM   problem_nodes
                           WHERE  node_name = "status")t_status
                 ON t_status.t_status_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_case_manager_id_problem,
                                  node_value AS case_manager
                           FROM   problem_nodes
                           WHERE  node_name = "case_manager")t_case_manager
                 ON t_case_manager.t_case_manager_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_ip_id_problem,
                                  node_value AS ip
                           FROM   problem_nodes
                           WHERE  node_name = "ip")t_ip
                 ON t_ip.t_ip_id_problem = main.id_problem
               INNER JOIN (SELECT id_problem as t_case_manager_eid_id_problem,
                                  node_value AS case_manager_eid
                           FROM   problem_nodes
                           WHERE  node_name = "case_manager_eid")
                          t_case_manager_eid
                 ON t_case_manager_eid.t_case_manager_eid_id_problem =
       main.id_problem)t  

这种检索数据的模式对我来说有点陌生,所以任何帮助都会受到赞赏。

3 个答案:

答案 0 :(得分:4)

您可以尝试使用此PIVOT技术。我做了前2例。你应该看看如何扩展它。

   SELECT main.*,
          MAX(CASE WHEN node_name = 'urgency' THEN node_value END) AS urgency,
          MAX(CASE WHEN node_name = 'name' THEN node_value END) AS name
   FROM   problems AS main INNER JOIN 
      problem_nodes pn ON pn.id_problem = main.id_problem
   WHERE node_name IN ('urgency','name')
   GROUP BY main.id_problem

答案 1 :(得分:1)

这基本上是EAV

子选择是不必要的 - 可以用这种形式清理:

SELECT t_urgency.node_value AS urgency,
       main.id_problem,
FROM problems AS main
INNER JOIN problem_nodes AS t_urgency
    ON t_urgency.id_problem = main.id_problem
    AND t_urgency.node_name = "urgency"

我会注意到INNER JOIN的独占使用是一个潜在的问题,因为在problem_nodes表中必须存在一个属性,以便结果集包含该行。

答案 2 :(得分:0)

原始查询基本上是查询EAV model非常笨拙的方法。你不需要所有这些JOIN。您只需要一系列相关的子查询。试试这个:

SELECT 
    (SELECT node_value FROM problem_nodes WHERE node_name = "urgency" AND id_problem = p.id_problem ) AS t_urgency,                              
    (SELECT node_value FROM problem_nodes WHERE node_name = "name" AND id_problem = p.id_problem ) AS t_name,
    (SELECT node_value FROM problem_nodes WHERE node_name = "phone" AND id_problem = p.id_problem ) AS t_phone,
    (SELECT node_value FROM problem_nodes WHERE node_name = "location" AND id_problem = p.id_problem ) AS t_location,
    (SELECT node_value FROM problem_nodes WHERE node_name = "department" AND id_problem = p.id_problem ) AS t_department,
    (SELECT node_value FROM problem_nodes WHERE node_name = "cc" AND id_problem = p.id_problem ) AS t_cc,
    (SELECT node_value FROM problem_nodes WHERE node_name = "status" AND id_problem = p.id_problem ) AS t_status,
    (SELECT node_value FROM problem_nodes WHERE node_name = "case_manager" AND id_problem = p.id_problem ) AS t_case_manager,
    (SELECT node_value FROM problem_nodes WHERE node_name = "ip" AND id_problem = p.id_problem ) AS t_ip,
    (SELECT node_value FROM problem_nodes WHERE node_name = "case_manager_eid" AND id_problem = p.id_problem ) AS t_case_manager_eid,
    id_problem,
    id_problem_type,
    eid_author,
    title,
    body,
    date_created,
    date_modified
FROM   
    problems AS p

我还应该提一下,如果没有索引problem_nodes.node_name列,你可能看不到性能提升。