简体   繁体   中英

How can I optimize this MySQL query in a stored procedure?

SET @count := (SELECT count(*)
               FROM dbo.ManyToManyTable SRSG
                        JOIN tableA SG on SRSG.a = SG.a
                        JOIN tableB SR on SRSG.b = SR.a
               WHERE SR.c = INPUT_VALUE);

IF (@count > 0)
THEN
    SELECT SG.fieldA, SG.fieldB
    FROM dbo.ManyToManyTable SRSG
             JOIN tableA SG on SRSG.a = SG.a
             JOIN tableB SR on SRSG.b = SR.a
    WHERE SR.c = INPUT_VALUE;
ELSE
    SELECT SG.a, SG.b FROM dbo.tableA SG WHERE SG.b = "default value";
END IF;

It's for a MySQL database. This works for me, but I hate the duplicate select query, but I don't know how to remove that duplication. The constraint is that everything has be in one store procedure.

You could write this as a single query:

with cte as (
      SELECT SG.fieldA, SG.fieldB
      FROM dbo.ManyToManyTable SRSG JOIN
           tableA SG
           on SRSG.salesGroupId = SG.salesGroupId JOIN
           tableB SR 
           on SRSG.salesRegionId = SR.salesRegionId
     WHERE SR.AField = INPUT_VALUE
    )
select *
from cte
union all
select SG.a, SG.b 
from dbo.tableA SG 
where SG.b = 'default value' and
      not exists (select 1 from cte);

MySQL tends to materialize CTEs (always?), so this should run the query once rather than twice.

A quick, but partial speedup is to replace

SET @count = ( SELECT COUNT(*) ... );
IF (@count > 0)

with this (using the rest of that initial SELECT):

IF ( EXISTS ( SELECT 1 FROM ... ) )

Also for performance, be sure to have in SRSG:

PRIMARY KEY(a,b)
INDEX(b,a)

and don't bother with an AUTO_INCREMENT.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM