Mysql 比大量使用条件联接更好的解决方案

Mysql 比大量使用条件联接更好的解决方案,mysql,join,Mysql,Join,我试图在MySql中创建一个“复杂”视图。我需要良好的性能,因为我必须每秒查询它2次,每个结果大约有1200行 我报告了一个包含数据的模式示例: CREATE TABLE objects ( object_id INT AUTO_INCREMENT, model_id INT, mode TINYINT, recipe_id INT, CONSTRAINT pk_objects PRIMARY KEY (object_id)); INSERT INTO objects (model_id, mo

我试图在MySql中创建一个“复杂”视图。我需要良好的性能,因为我必须每秒查询它2次,每个结果大约有1200行

我报告了一个包含数据的模式示例:

CREATE TABLE objects (
object_id INT AUTO_INCREMENT,
model_id INT,
mode TINYINT,
recipe_id INT,
CONSTRAINT pk_objects PRIMARY KEY (object_id));
INSERT INTO objects (model_id, mode, recipe_id) VALUES (1, 0, 1), (1, 1, 1), (2, 1, 1);

CREATE TABLE models (
model_id INT AUTO_INCREMENT,
family_id INT,
CONSTRAINT pk_models PRIMARY KEY (model_id));
INSERT INTO models (family_id) VALUES (0), (1);

CREATE TABLE models_recipes (
model_id INT,
recipe_id INT,
distinction_id INT,
CONSTRAINT pk_models_recipes PRIMARY KEY (model_id, recipe_id, distinction_id));
INSERT INTO models_recipes (model_id, recipe_id, distinction_id) VALUES (1, 2, 1), (1, 3, 2);

CREATE TABLE families (
family_id INT AUTO_INCREMENT,
name VARCHAR(45),
CONSTRAINT pk_families PRIMARY KEY (family_id));
INSERT INTO families (name) VALUES ("Family_1");

CREATE TABLE families_recipes (
family_id INT,
recipe_id INT,
distinction_id INT,
CONSTRAINT pk_families_recipes PRIMARY KEY (family_id, recipe_id, distinction_id));
INSERT INTO families_recipes (family_id, recipe_id, distinction_id) VALUES (1, 3, 1), (1, 2, 2);

CREATE TABLE recipes (
recipe_id INT AUTO_INCREMENT,
name VARCHAR(45),
CONSTRAINT pk_recipes PRIMARY KEY (recipe_id));
INSERT INTO recipes (name) VALUES ("recipe1"), ("recipe2"), ("recipe3");
我的视图需要在以下不同条件下报告配方名称:

  • 如果“objects.mode”为0->“object.recipe\u id”的名称
  • 如果“objects.mode”为1
    • 如果“models.family\u id>0”->“families\u recipes.recipe\u id”的名称,其中differention\u id=foo
    • ELSE->“models\u recipes.recipe\u id”的名称,其中differention\u id=foo
我写了这个查询:

SELECT o.object_id, o.mode, o.model_id, 
CASE
    WHEN o.mode = 1 THEN
        CASE
            WHEN m.family_id > 0 THEN rf.name
            ELSE rm.name
        END
    WHEN o.mode = 0 THEN ro.name
END AS 'recipe_name'
FROM objects AS o
LEFT JOIN models AS m
ON o.model_id = m.model_id

LEFT JOIN (SELECT * FROM models_recipes WHERE distinction_id = 1) AS mr
ON m.model_id = mr.model_id
LEFT JOIN recipes AS rm
ON mr.recipe_id = rm.recipe_id

LEFT JOIN (SELECT * FROM families_recipes WHERE distinction_id = 1) AS fr
ON m.family_id = fr.family_id
LEFT JOIN recipes AS rf
ON fr.recipe_id = rf.recipe_id

LEFT JOIN recipes AS ro
ON o.recipe_id = ro.recipe_id;
结果是正确的

object_id | mode | model_id | recipe_name
-----------------------------------------
1         | 0    | 1        | recipe1
2         | 1    | 1        | recipe2
3         | 1    | 2        | recipe3

但是我正在寻找一个更好的解决方案,避免加入想要的数据(配方)的次数等于条件的次数。
谢谢

如果您使用条件聚合,您只能加入一次
配方

select o.object_id, o.mode, o.model_id,
  case o.mode
    when 0 then max(case when r.recipe_id = o.recipe_id then r.name end)
    when 1 then case
      when m.family_id > 0 then max(case when r.recipe_id = fr.recipe_id then r.name end)
      else max(case when r.recipe_id = mr.recipe_id then r.name end)
    end
  end recipe_name 
from objects o
left join models m on m.model_id = o.model_id
left join families f on f.family_id = m.family_id
left join families_recipes fr on fr.family_id = f.family_id and fr.distinction_id = 1
left join models_recipes mr on mr.model_id = m.model_id and mr.distinction_id = 1
left join recipes r on r.recipe_id in (o.recipe_id, fr.recipe_id, mr.recipe_id) 
group by o.object_id, o.mode, o.model_id
请参阅。
结果:


将整个查询粘贴到这里,这样我们可以帮助更好地发布。给出你所需要的&把它和你的问题联系起来。仅将图像用于不能表示为文本或扩充文本的内容。请在代码问题中给出一个--cut&paste&runnable代码,包括作为代码输入的最小代表性示例;期望和实际输出(包括逐字记录错误消息);标签和版本;清晰的说明和解释。对于包含DBMS和DDL(包括约束和索引)以及以表格式作为代码输入的SQL@Ehsan我重新编写了这个问题,添加了整个queryI基准测试了这个解决方案,似乎表现得又好又快!谢谢你能解释一下为什么这个解决方案会更好吗?
object_id | mode | model_id | recipe_name
--------: | ---: | -------: | :----------
        1 |    0 |        1 | recipe1    
        2 |    1 |        1 | recipe2    
        3 |    1 |        2 | recipe3