采用以下两个模拟表:
dbo.animal
id name
1 dog
2 cat
dbo.animal_food
id animal_id food_id active
1 1 4 1
2 1 5 1
我需要根据不同的排序结果查询animal
多个animal_food
子查询。像这样:
select name,
( select top 1 food_id
from animal_food
where animal_id = animal.id
order by food_id desc) as max_food_id,
( select top 1 food_id
from animal_food
where animal_id = animal.id
and active = 1
order by food_id desc) as max_active_food_id,
from animal
这显然效率很低 - 我需要加快速度。但是,我无法弄清楚如何将其重构为可以提高性能的连接。
答案 0 :(得分:1)
如果您只想要指定的两个food_id值,则可以将join
与group by
以及所谓的条件聚合一起使用,如下所示:
select
name,
max(animal_food.food_id) as max_food_id,
max(case when animal_food.active = 1 then animal_food.food_id else null end) as max_active_food_id,
from animal
inner join animal_food on animal.animal_id = animal_food.animal_id
group by animal.animal_id, animal.name
答案 1 :(得分:1)
这看起来像一个简单的聚合查询,唯一的变化是第三列只考虑request.setAttribute
food_id
的最大值active = 1
。如果是这种情况,这将完成没有子查询的工作:
SELECT
name,
MAX(food_id) AS max_food_id,
MAX(CASE WHEN active = 1 THEN food_id END) AS max_active_food_id
FROM animal
JOIN animal_food = animal.id = animal_food.id
GROUP BY name
如果MAX(CASE WHEN active = 1 THEN food_id END)
不等于1,NULL
将返回active
,而MAX
等聚合会忽略空值。
答案 2 :(得分:1)
您还可以使用交叉应用功能并检查哪种方式表现更好
select name,
max_food_id.food_id AS max_food_id,
max_active_food_id.food_id AS max_active_food_id,
from animal
cross apply (
select top 1 food_id
from animal_food
where animal_id = animal.id
order by food_id desc
) AS max_food_id
cross apply
( select top 1 food_id
from animal_food
where animal_id = animal.id
and active = 1
order by food_id desc) as max_active_food_id
答案 3 :(得分:0)
我不确定性能,但这里是使用连接和聚合的查询。这是你正在寻找的还是你已经尝试过这个?
select animal.name
, max(animal_food_all.food_id) as max_food_id
, max(animal_food_active.food_id) as max_active_food_id
from animal
left outer join animal_food as animal_food_all on animal.id = animal_food_all.animal_id
left outer join animal_food as animal_food_active on animal.id = animal_food_active.animal_id and animal_food_active.active = 1
GROUP BY animal.name
我使用了外连接,以防有动物没有列出食物,如果你想要省略那些你可以改变它的内连接,但无论哪种方式,它可能对性能影响很小(如果有的话)。