SQL查询返回异常大的计数

时间:2014-10-15 20:29:45

标签: mysql sql

我的架构大致转换为以下内容:

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的租金。

我做错了什么?

3 个答案:

答案 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子句。