-1

我正在尝试在 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");

我的视图需要在这些不同的条件下报告配方名称:

  • IF 'objects.mode' 为 0 -> 'object.recipe_id' 的名称
  • IF 'objects.mode' 为 1
    • IF 'models.family_id > 0' -> 'families_recipes.recipe_id' 的名称 WHERE distinct_id = foo
    • ELSE -> 'models_recipes.recipe_id' 的名称 WHERE distinct_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

但我正在寻找更好的解决方案,避免加入所需数据(食谱)的次数等于数量条件。谢谢

4

1 回答 1

1

recipes如果使用条件聚合,则只能加入一次:

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

请参阅演示
结果:

object_id | mode | model_id | recipe_name
--------: | ---: | -------: | :----------
        1 |    0 |        1 | recipe1    
        2 |    1 |        1 | recipe2    
        3 |    1 |        2 | recipe3   
于 2020-10-08T12:25:29.157 回答