2012-03-09 257 views
3

嗨,我正在构建一个Java程序,我需要管理一些项目。为了做到这一点,我需要过滤项目。我通过构建SQL查询并执行它来过滤项目。我需要以下查询首先排序 (LEFT JOIN (SELECT * FROM grupe ORDER BY grupe.pavadinimas DESC)grupe ON) 并且只有然后添加所有其他数据并执行WHERE子句。MySQL按优先顺序排列

SELECT * 
FROM (
     (
     SELECT preke.* 
     FROM preke_tiekejas 
       , preke 
     WHERE preke_tiekejas.tiek_id IN (18610,13604) 
       AND preke.pr_id=preke_tiekejas.pr_id 
     GROUP BY 
       preke_tiekejas.pr_id 
    ) preke 
     , preke_kaina 
     , (
     SELECT * 
     FROM preke_info 
     WHERE preke_info.pavadinimas LIKE '%kait%' 
    ) preke_info 
    ) LEFT JOIN (
     SELECT * 
     FROM grupe 
     ORDER BY 
       grupe.pavadinimas DESC 
    )grupe ON grupe.pgs_id=preke.pgs_id 
    LEFT JOIN gamintojas ON gamintojas.gam_id=preke.gam_id 
    LEFT JOIN grupe_darb ON grupe_darb.pgs_id=grupe.pgs_id 
WHERE preke_kaina.pr_id=preke.pr_id 
    AND preke_info.pr_id=preke.pr_id 
    AND grupe_darb.darb_id = 20 
LIMIT 0, 500 

如果我删除这些两个子查询:

(SELECT * FROM preke_info WHERE preke_info.pavadinimas LIKE '%kait%') 

(SELECT preke.* FROM preke_tiekejas, preke 
WHERE preke_tiekejas.tiek_id IN (18610,13604) 
AND preke.pr_id=preke_tiekejas.pr_id 
GROUP BY preke_tiekejas.pr_id) 

那么查询的工作就是我想要的。

P.S.命令它只在查询结束时不是一个选项,因为有大量的记录,然后它变得缓慢地狱。

解释

http://i40.tinypic.com/wirbz6.jpg

@Lieven

查询的结果是不相同 - 无极限应为〜90K行: enter image description here

查询结果一样 - 回归〜50rows: enter image description here

回答

1

我觉得很难读您的查询,我将其重新格式化为这个

重新格式化

SELECT * 
FROM (
      (
      SELECT preke.* 
      FROM preke_tiekejas 
        , preke 
      WHERE preke_tiekejas.tiek_id IN (18610,13604) 
        AND preke.pr_id=preke_tiekejas.pr_id 
      GROUP BY 
        preke_tiekejas.pr_id 
     ) preke 
      , preke_kaina 
      , (
      SELECT * 
      FROM preke_info 
      WHERE preke_info.pavadinimas LIKE '%kait%' 
     ) preke_info 
     ) LEFT JOIN (
      SELECT * 
      FROM grupe 
      ORDER BY 
        grupe.pavadinimas DESC 
     )grupe ON grupe.pgs_id=preke.pgs_id 
     LEFT JOIN gamintojas ON gamintojas.gam_id=preke.gam_id 
     LEFT JOIN grupe_darb ON grupe_darb.pgs_id=grupe.pgs_id 
WHERE preke_kaina.pr_id=preke.pr_id 
     AND preke_info.pr_id=preke.pr_id 
     AND grupe_darb.darb_id = 20 
LIMIT 0, 500 

重新格式化之后,我会删除隐含的JOIN语法。你应该总是尝试使用明确的JOIN的可读性和可维护性。隐含的JOIN语法迟早会过时。

使用明确连接

SELECT * 
FROM ((
      SELECT preke.* 
      FROM preke_tiekejas 
        INNER JOIN preke ON preke.pr_id=preke_tiekejas.pr_id 
      WHERE preke_tiekejas.tiek_id IN (18610,13604)      
      GROUP BY 
        preke_tiekejas.pr_id 
     ) preke 
      INNER JOIN preke_kaina preke_kaina.pr_id=preke.pr_id 
      INNER JOIN (
      SELECT * 
      FROM preke_info 
      WHERE preke_info.pavadinimas LIKE '%kait%' 
     ) preke_info ON preke_info.pr_id=preke.pr_id 
     ) LEFT JOIN (
      SELECT * 
      FROM grupe 
      ORDER BY 
        grupe.pavadinimas DESC 
     )grupe ON grupe.pgs_id=preke.pgs_id 
     LEFT JOIN gamintojas ON gamintojas.gam_id=preke.gam_id 
     LEFT JOIN grupe_darb ON grupe_darb.pgs_id=grupe.pgs_id 
WHERE grupe_darb.darb_id = 20 
LIMIT 0, 500 

现在冗余子查询中脱颖而出。我可能会关闭,但我相信你的说法可以进一步降低该

删除冗余的子查询

SELECT * 
FROM (
      SELECT preke.* 
      FROM preke_tiekejas 
        INNER JOIN preke ON preke.pr_id=preke_tiekejas.pr_id 
      WHERE preke_tiekejas.tiek_id IN (18610,13604)      
      GROUP BY 
        preke_tiekejas.pr_id 
     ) preke 
     INNER JOIN preke_kaina preke_kaina.pr_id=preke.pr_id 
     INNER JOIN preke_info ON preke_info.pr_id=preke.pr_id 
     LEFT OUTER JOIN grupe ON grupe.pgs_id=preke.pgs_id 
     LEFT OUTER JOIN gamintojas ON gamintojas.gam_id=preke.gam_id 
     LEFT OUTER JOIN grupe_darb ON grupe_darb.pgs_id=grupe.pgs_id 
WHERE grupe_darb.darb_id = 20 
     AND preke_info.pavadinimas LIKE '%kait%' 
ORDER BY 
     grupe.pavadinimas DESC 
LIMIT 0, 500 

现在,对我来说,这是一个查询我可以工作。不幸的是,我没有看到任何明显的性能问题,即正确的索引无法解决。

你能告诉我们你的查询的执行计划吗?

+1

如果我理解正确,这就是你想要的:http://i44.tinypic.com/ibl64i.jpg – Minutis 2012-03-09 07:40:55

+0

@Minutis - 是的。我已将它添加到您的问题。你能否验证我的修改后的声明是否提供了与原始查询相同的结果? – 2012-03-09 07:53:05

+0

@Minutis - 现在我是阅读MySQL解释计划的外行,但是在我看来,你错过了'grupe_darb'上的索引。 – 2012-03-09 07:58:46