我的架构大致转换为以下内容:
reservation: reservation_id, inventory_id
inventory: inventory_id, car_id
car: car_id
feature: feature_id, name
car_feature: car_id, feature_id
设计相对简单。省略了一些不必要的列,但基本思路是对库存项目进行预留。库存物品可以是具有car_ids的汽车。汽车可以具有许多功能(并且可以应用于多辆汽车的功能)。
我想要做的是找到针对每种类型的功能进行的预订数量。示例:一个表格,其中一列是特征"名称",另一列是具有该功能的汽车的预订数量。出于迂腐的原因,我不想要使用任何嵌套查询。
以下是我尝试的查询:
select f.name, count(*) as reservation_count
from reservation r, inventory i, car c, car_feature cf, feature f
where r.inventory_id = i.inventory_id and i.car_id = cf.car_id and cf.feature_id = f.feature_id
group by f.name;
查询正确返回以下结果表集中的每个命名要素:
-name- -reservation_count-
spokes 945000
wheels 931000
sunroof 104000
... ...
然而,计算需要花费非常大的时间(数千行的数据集为11秒),并且预订计数太高 - 数据库中只有16k的租金。
我做错了什么?
答案 0 :(得分:2)
尝试从您的查询中选择“car c”。这将取出一些冗余行,因为您没有加入它。将它包含在您的工作方式中只需制作每个功能的n-car副本。
为了提高速度,请尝试为您加入的列编制索引。 (参见DESCRIBE评论)
答案 1 :(得分:2)
我认为以下查询将返回您需要的结果
Select feature.name, COUNT(reservation.reservation_id) as reservation_count
from feature
inner join car_feature on feature.feature_id=car_feature.feature_id
inner join car on car_feature.car_id=car.car_id
inner join inventory on car.car_id=inventory.car_id
inner join reservation on inventory.inventory_id = reservation.inventory_id
GROUP BY feature.name
答案 2 :(得分:2)
你问题的一大部分是你使用旧的skool,ANSI / ISO之前的联接。这让你很难看到自己在做什么。
让我们把你的原始查询和格式化,这样我们就可以更容易地看到发生了什么:
select f.name ,
count(*) as reservation_count
from reservation r ,
inventory i ,
car c ,
car_feature cf ,
feature f
where r.inventory_id = i.inventory_id
and i.car_id = cf.car_id
and cf.feature_id = f.feature_id
group by f.name
;
现在,让我们将其转换为ANSI连接语法:
select f.name ,
count(*) as reservation_count
from reservation r
join inventory i on i.inventory_id = r.inventory_id
join car c on ???
join car_feature cf on cf.car_id = i.car_id
join feature f on f.feature_id = cf.feature_id
group by f.name
嗯......那看起来不太对劲,是吗?不知何故,car
表似乎已从连接标准中省略。
如果我们以可能的方式充实事物,使用您提供的架构,我们会得到类似的结果:
select f.name ,
count(*) as reservation_count
from reservation r
join inventory i on i.inventory_id = r.inventory_id
join car c on c.car_id = i.care_id
join car_feature cf on cf.car_id = c.car_id
join feature f on f.feature_id = cf.feature_id
group by f.name
这可能会为您提供所需的结果。
您可能会注意到它也更容易阅读和理解。
作为额外的奖励,解决问题要容易得多。将语句更改为select count(*)
,注释掉所有join子句和where子句(如果有),因此
select --f.name ,
--count(*) as reservation_count
count(*)
from reservation r
--join inventory i on i.inventory_id = r.inventory_id
--join car c on c.car_id = i.care_id
--join car_feature cf on cf.car_id = c.car_id
--join feature f on f.feature_id = cf.feature_id
--group by f.name
运行它应该为您提供原始数字预留。
将联接添加到库存表
select --f.name ,
--count(*) as reservation_count
count(*)
from reservation r
join inventory i on i.inventory_id = r.inventory_id
--join car c on c.car_id = i.care_id
--join car_feature cf on cf.car_id = c.car_id
--join feature f on f.feature_id = cf.feature_id
--group by f.name
应该给你,我想,同样的预订计数。如果这个数字与您的预期不同,那么您的加入条件不正确或者您不能完全理解所涉及的关系的基数,这是一个很好的变化。
重复此操作,直到您重新添加所有已连接的表格。然后开始一次取消注释where
子句,验证您的数字是否符合预期。
如果您对查询结果感到满意,请将结果列表中的列放回原位并取消注释group by
子句。