优化 MS Access 双子查询
Optimize MS Access Double SubQuery
我正在构建的这个 MS Access 查询非常慢。我只测试一个月的数据(一个 table 驱动此查询有 28,577 条记录,36 列)。
这是我想要完成的:
我想 return 在特定交易类型中按型号销售的独特车辆的数量(此数据库未规范化,并且是根据 excel sheet 加载的变成 table)。
存在第一个子查询是因为据我所知,在 Access 中您不能将 DISTINCT 语句与聚合函数一起使用。所以我需要构建一个子查询来处理 Count(DISTINCT VIN)。
我认为第二个子查询是罪魁祸首。每个 VIN 可能有很多条目。例如,车辆可能已使用我正在计算的交易类别之一售出,然后被取消,并转售到我不想计算的交易类别之一。这将为此 VIN 生成三个记录:
- 销售到我认为我想统计的交易类别
- 取消第一次销售
- 转售成我不想算的交易类别
第二个子查询检查 VIN 是否有 "cancelled Sale" 记录,然后不将第一个 Sale 计入计数。
希望我解释得很好,有人可以为我提供一个可能的解决方案来加速这个查询。
谢谢
查询
PARAMETERS [Enter Sales Month Start Date] DATETIME, [Enter Sales Month End Date]
DATETIME;
SELECT DSTNCT_COUNT.trans AS Trans,
DSTNCT_COUNT.mdl AS Model,
Count(DSTNCT_COUNT.cnt) AS VIN_COUNT
FROM (SELECT DISTINCT new_bbss.vin AS cNt,
new_bbss.[model category] AS MDL,
new_bbss.[trans category] AS Trans
FROM new_bbss
WHERE ( ( ( new_bbss.[trans category] ) NOT LIKE 'Individual'
AND ( new_bbss.[trans category] ) NOT LIKE 'Corporate'
AND ( new_bbss.[trans category] ) NOT LIKE 'Cancel'
AND ( new_bbss.[trans category] ) NOT LIKE 'Partners'
AND ( new_bbss.[trans category] ) NOT LIKE 'Special'
AND ( new_bbss.[trans category] ) NOT LIKE 'Employee'
AND ( new_bbss.[trans category] ) NOT LIKE 'Mobile'
AND ( new_bbss.[trans category] ) NOT LIKE 'JLR FLEET' )
AND ( ( new_bbss.[retailer code] ) LIKE 'R*' ) )
AND new_bbss.[trans date] BETWEEN [enter sales month start date]
AND
[enter sales month end date]
AND new_bbss.vin NOT IN(SELECT new_bbss.vin
FROM new_bbss
WHERE new_bbss.[trans category] LIKE
'CancelVIP*'
OR new_bbss.[trans category] LIKE
'CancelDealer Local*'
OR new_bbss.[trans category] LIKE
'CancelLoaner*'
OR new_bbss.[trans category] LIKE
'CancelAlive*'))
AS DSTNCT_COUNT
GROUP BY trans, mdl;
MsAccess 在 NOT IN 上应该比在 NOT EXISTS 上慢。我不知道这是不是真的,但你可以试试。此外,您可以将此限制从 WHERE 子句移至 HAVING 子句,因为 vin 在 GROUP BY 子句中。这可能会减少 MsAccess 必须查找的次数。
select [model category], [trans category], count(*)
from
(
select [model category], [trans category], vin
from new_bbss
where [trans category] not like 'Individual'
and [trans category] not like 'Corporate'
and [trans category] not like 'Cancel'
and [trans category] not like 'Partners'
and [trans category] not like 'Special'
and [trans category] not like 'Employee'
and [trans category] not like 'Mobile'
and [trans category] not like 'JLR FLEET'
and [retailer code] like 'R*'
and [trans date] between [enter sales month start date]
and [enter sales month end date]
group by [model category], [trans category], vin
having not exists
(
select *
from new_bbss unwanted
where unwanted.vin = new_bbss.vin
and
( unwanted.[trans category] like 'CancelVIP*'
or unwanted.[trans category] like 'CancelDealer Local*'
or unwanted.[trans category] like 'CancelLoaner*'
or unwanted.[trans category] like 'CancelAlive*'
)
)
) matches
group by [model category], [trans category];
顺便说一句:vin 上应该有一个索引,这样MsAccess 可以快速查找它的记录。
我正在构建的这个 MS Access 查询非常慢。我只测试一个月的数据(一个 table 驱动此查询有 28,577 条记录,36 列)。
这是我想要完成的:
我想 return 在特定交易类型中按型号销售的独特车辆的数量(此数据库未规范化,并且是根据 excel sheet 加载的变成 table)。
存在第一个子查询是因为据我所知,在 Access 中您不能将 DISTINCT 语句与聚合函数一起使用。所以我需要构建一个子查询来处理 Count(DISTINCT VIN)。
我认为第二个子查询是罪魁祸首。每个 VIN 可能有很多条目。例如,车辆可能已使用我正在计算的交易类别之一售出,然后被取消,并转售到我不想计算的交易类别之一。这将为此 VIN 生成三个记录:
- 销售到我认为我想统计的交易类别
- 取消第一次销售
- 转售成我不想算的交易类别
第二个子查询检查 VIN 是否有 "cancelled Sale" 记录,然后不将第一个 Sale 计入计数。
希望我解释得很好,有人可以为我提供一个可能的解决方案来加速这个查询。
谢谢
查询
PARAMETERS [Enter Sales Month Start Date] DATETIME, [Enter Sales Month End Date]
DATETIME;
SELECT DSTNCT_COUNT.trans AS Trans,
DSTNCT_COUNT.mdl AS Model,
Count(DSTNCT_COUNT.cnt) AS VIN_COUNT
FROM (SELECT DISTINCT new_bbss.vin AS cNt,
new_bbss.[model category] AS MDL,
new_bbss.[trans category] AS Trans
FROM new_bbss
WHERE ( ( ( new_bbss.[trans category] ) NOT LIKE 'Individual'
AND ( new_bbss.[trans category] ) NOT LIKE 'Corporate'
AND ( new_bbss.[trans category] ) NOT LIKE 'Cancel'
AND ( new_bbss.[trans category] ) NOT LIKE 'Partners'
AND ( new_bbss.[trans category] ) NOT LIKE 'Special'
AND ( new_bbss.[trans category] ) NOT LIKE 'Employee'
AND ( new_bbss.[trans category] ) NOT LIKE 'Mobile'
AND ( new_bbss.[trans category] ) NOT LIKE 'JLR FLEET' )
AND ( ( new_bbss.[retailer code] ) LIKE 'R*' ) )
AND new_bbss.[trans date] BETWEEN [enter sales month start date]
AND
[enter sales month end date]
AND new_bbss.vin NOT IN(SELECT new_bbss.vin
FROM new_bbss
WHERE new_bbss.[trans category] LIKE
'CancelVIP*'
OR new_bbss.[trans category] LIKE
'CancelDealer Local*'
OR new_bbss.[trans category] LIKE
'CancelLoaner*'
OR new_bbss.[trans category] LIKE
'CancelAlive*'))
AS DSTNCT_COUNT
GROUP BY trans, mdl;
MsAccess 在 NOT IN 上应该比在 NOT EXISTS 上慢。我不知道这是不是真的,但你可以试试。此外,您可以将此限制从 WHERE 子句移至 HAVING 子句,因为 vin 在 GROUP BY 子句中。这可能会减少 MsAccess 必须查找的次数。
select [model category], [trans category], count(*)
from
(
select [model category], [trans category], vin
from new_bbss
where [trans category] not like 'Individual'
and [trans category] not like 'Corporate'
and [trans category] not like 'Cancel'
and [trans category] not like 'Partners'
and [trans category] not like 'Special'
and [trans category] not like 'Employee'
and [trans category] not like 'Mobile'
and [trans category] not like 'JLR FLEET'
and [retailer code] like 'R*'
and [trans date] between [enter sales month start date]
and [enter sales month end date]
group by [model category], [trans category], vin
having not exists
(
select *
from new_bbss unwanted
where unwanted.vin = new_bbss.vin
and
( unwanted.[trans category] like 'CancelVIP*'
or unwanted.[trans category] like 'CancelDealer Local*'
or unwanted.[trans category] like 'CancelLoaner*'
or unwanted.[trans category] like 'CancelAlive*'
)
)
) matches
group by [model category], [trans category];
顺便说一句:vin 上应该有一个索引,这样MsAccess 可以快速查找它的记录。