FIND_IN_SET很慢,不能使用IN()

时间:2015-02-07 16:10:16

标签: mysql

我有一个存储过程并且运行缓慢。有没有更好的方法将表id传递给过程而不是使用FIND_IN_SET?

表格列e.fk_trans_history_id是INT(32)

DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `1_trans_hist_ent_items_sel`(b INT,tid TEXT)
BEGIN
SELECT 
    e.id,
    e.fk_trans_history_id,
    e.fk_prod_pack_id,
    e.line_num,
    e.vat_code,
    e.code,
    e.make,
    e.model,
    e.price,
    e.discount,
    e.cover,
    e.warranty,
    p.make,
    p.model,
    p.weight,
    p.width,
    p.depth,
    p.height,
    p.cost,
    p.cover_value_each,
    p.web_model,
    k.stock - k.repair
FROM
    1_trans_history_entries e
        LEFT JOIN
    1_products p ON p.id = e.fk_prod_pack_id
        AND LEFT(code, 1) <> 'P'
        LEFT JOIN
    1_stock k ON k.fk_products_id = p.id AND k.branch = b
WHERE
    (e.code IN ('MiscShip' , 'Collect')
        OR (ASCII(e.code) > 47
        AND ASCII(e.code) < 58))
        AND FIND_IN_SET(e.fk_trans_history_id, tid)
ORDER BY e.id;
END

3 个答案:

答案 0 :(得分:1)

将您要匹配的ID放入临时表中,然后加入该表。

CREATE TEMPORARY TABLE temp_trans_hist_ent_items_sel_ids (
    id
);
INSERT INTO temp_trans_hist_ent_items_sel_ids VALUES (1), (10), ...;

然后程序中的查询可以使用:

JOIN temp_trans_hist_ent_items_sel_ids AS temp ON e.fk_trans_history_id = temp.id

答案 1 :(得分:0)

我发现最好也是最快的是准备这样的查询。

CREATE DEFINER = root @ localhost程序1_trans_hist_ent_items_sel(b INT,tid TEXT)

BEGIN

SET @ query = CONCAT(' 选择     e.id,     e.fk_trans_history_id,     e.fk_prod_pack_id,     e.line_num,     e.vat_code,     e.code,     e.make,     e.model,     e.price,     e.discount,     e.cover,     e.warranty,     p.make,     p.model,     p.weight,     p.width,     p.depth,     p.height,     p.cost,     p.cover_value_each,     p.web_model,     k.stock - k.repair 从     1_trans_history_entries e         LEFT JOIN     1_products p ON p.id = e.fk_prod_pack_id         AND LEFT(代码,1)&lt;&gt; \ 'P \'         LEFT JOIN     1_stock k ON k.fk_products_id = p.id AND k.branch =',b,' 哪里     (e.code IN(\'MiscShip \',\'Collect \')         或(ASCII(e.code)> 47         AND ASCII(e.code)&lt; 58))         AND e.fk_trans_history_id IN(',tid,')

ORDER BY e.id;');

PREPARE sql_query FROM @query;

EXECUTE sql_query;

SET @query ='';

END

答案 2 :(得分:0)

感谢Stephen Bouffe。我的代码更短,更容易理解和实现此解决方案。就我而言,看起来像这样

SET @query=CONCAT( '
    DELETE FROM markup
    WHERE id IN (', @ids, ');
');

PREPARE sql_query FROM @query;
EXECUTE sql_query;

@ids是类似“ 7,12,52”的字符串。 它的运行速度快得多,然后是FIND_IN_SET。