我在客戶的一個網站上有一個頁面,它生成一個廣泛的報告,從整個網站的MS Access數據庫中的大量表格中提取數據。該網站的一個不幸的架構問題是存在兩個幾乎相同的表,它們代表相同的「類型」數據,但其中一個是「舊」版本,另一個是「新」版本。生成報告時,我需要對兩個相似的表執行一些聚合操作。初始查詢將這些表連接到其餘數據,並在連接的表上調用適當的聚合函數。不久,我意識到一個連接將無法正常工作,因爲這兩個表不一定有相同的行數,從而導致聚合函數不正確地將這兩行中的行分組...MS Access - 查詢重構幫助
這是MSSQL還是MySQL我可能創建一個包含來自兩個表的複合數據的VIEW,但不幸的是我被困在MS Access中,這些「新穎」的概念不存在......我能夠提出的解決方案的工作,但必須是一些我見過的最醜陋的SQL。基本上,我創建了一個SQL查詢,其中包括來自多個連接表的所有適當列和兩個相似表中的一個。然後,我創建了第二個包含所有相同字段的SQL查詢並加入其他類似的表。最後,我將這兩個查詢包裝到外部查詢的FROM
子句中的子查詢中。
最終結果是一個大量的查詢,其中包含大量的重複選擇,我只是因爲需要從兩個相似的表中彙總數據而包含這些選擇。我真的想重構查詢到一些不太可怕的事情,但我不知道從哪裏開始......有什麼建議嗎?
SELECT contractid,
pholderid,
policyholdername,
policyholdercity,
policyholderstate,
vehicleyear,
vehiclemake,
vehiclemodel,
Iif(claimmileage > vehiclemileage, claimmileage, vehiclemileage) AS mileage,
clientname,
contracttype,
contractmonths,
wholesaleprice,
begindate,
cancelleddate,
cancelledalphatotal,
paiddate,
voided,
Sum(claimscost) AS totalclaimscost,
Sum(claimscount) AS totalclaimscount,
DateAdd('m', contractmonths, begindate) AS expirationdate,
Iif(paiddate IS NOT NULL AND contractmonths > 0,
Iif(voided = true,
Iif(cancelleddate IS NOT NULL,
Iif(((cancelleddate - begindate)/(364.25/12)) >= contractmonths,
1,
((cancelleddate - begindate)/(364.25/12))/contractmonths),
Iif(((Date() - begindate)/(364.25/12)) >= (contractmonths),
1,
((Date() - begindate)/(364.25/12))/contractmonths)),
((Date() - begindate)/(364.25/12))/contractmonths),
0) AS earnedfactor,
(earnedfactor * wholesaleprice) AS earnedpremium,
Iif(voided = true, 0, (wholesaleprice - earnedpremium)) AS unearnedpremium,
Iif(voided = true AND cancelledalphatotal IS NOT NULL, cancelledalphatotal, 0) AS refund,
Iif(earnedpremium > 0,totalclaimscost/earnedpremium, 0) AS lossratio
FROM (SELECT contracts.id AS contractid,
policyholders.id AS pholderid,
policyholders.firstname
+ ' '
+ policyholders.lastname AS policyholdername,
policyholders.city AS policyholdercity,
policyholders.state AS policyholderstate,
vehicles.yr AS vehicleyear,
vehicles.make AS vehiclemake,
vehicles.model AS vehiclemodel,
vehicles.mileage AS vehiclemileage,
clients.coname AS clientname,
contracttypes.name AS contracttype,
coverageavailable.contractmonths AS contractmonths,
contracts.contractwholesalecost AS wholesaleprice,
contracts.begindate AS begindate,
contracts.cancelledon AS cancelleddate,
contracts.cancelledalphatotal AS cancelledalphatotal,
contracts.paidon AS paiddate,
contracts.voided AS voided,
Sum(Iif(claims.totalrepaircost IS NULL,0,claims.totalrepaircost)) AS claimscost,
Count(claims.id) AS claimscount,
Max(Iif(claims.currentmileage IS NULL,0,claims.currentmileage)) AS claimmileage
FROM claims
RIGHT JOIN (coverageavailable
INNER JOIN ((((policyholders
INNER JOIN clients
ON policyholders.clientid = clients.id)
INNER JOIN contracts
ON policyholders.id = contracts.policyholderid)
INNER JOIN vehicles
ON contracts.vehicleid = vehicles.id)
INNER JOIN contracttypes
ON contracts.contracttypeid = contracttypes.id)
ON coverageavailable.id = contracts.termid)
ON claims.policyholderid = policyholders.id
WHERE contractmonths > 0
AND contracts.begindate IS NOT NULL
AND contracttypes.id <> 3
GROUP BY contracts.id,
policyholders.id,
policyholders.firstname,
policyholders.lastname,
policyholders.city,
policyholders.state,
vehicles.yr,
vehicles.make,
vehicles.model,
vehicles.mileage,
clients.coname,
contracttypes.name,
coverageavailable.contractmonths,
contracts.contractwholesalecost,
contracts.begindate,
contracts.cancelledon,
contracts.paidon,
contracts.voided,
contracts.cancelledalphatotal
UNION
SELECT contracts.id AS contractid,
policyholders.id AS pholderid,
policyholders.firstname
+ ' '
+ policyholders.lastname AS policyholdername,
policyholders.city AS policyholdercity,
policyholders.state AS policyholderstate,
vehicles.yr AS vehicleyear,
vehicles.make AS vehiclemake,
vehicles.model AS vehiclemodel,
vehicles.mileage AS vehiclemileage,
clients.coname AS clientname,
contracttypes.name AS contracttype,
coverageavailable.contractmonths AS contractmonths,
contracts.contractwholesalecost AS wholesaleprice,
contracts.begindate AS begindate,
contracts.cancelledon AS cancelleddate,
contracts.cancelledalphatotal AS cancelledalphatotal,
contracts.paidon AS paiddate,
contracts.voided AS voided,
Sum(Iif(claim.inspector1paidout IS NULL,0,claim.inspector1paidout))
+ Sum(Iif(claim.inspector2paidout IS NULL,0,claim.inspector2paidout))
+ Sum(Iif(claim.mechanicpaidout IS NULL,0,claim.mechanicpaidout))
+ Sum(Iif(claim.partdealerpaidout IS NULL,0,claim.partdealerpaidout)) AS claimscost,
Count(claim.id) AS claimscount,
Max(Iif(claim.mileage IS NULL,0,claim.mileage)) AS claimmileage
FROM claim
RIGHT JOIN (coverageavailable
INNER JOIN ((((policyholders
INNER JOIN clients
ON policyholders.clientid = clients.id)
INNER JOIN contracts
ON policyholders.id = contracts.policyholderid)
INNER JOIN vehicles
ON contracts.vehicleid = vehicles.id)
INNER JOIN contracttypes
ON contracts.contracttypeid = contracttypes.id)
ON coverageavailable.id = contracts.termid)
ON claim.contractid = contracts.id
WHERE contractmonths > 0
AND contracts.begindate IS NOT NULL
AND contracttypes.id <> 3
GROUP BY contracts.id,
policyholders.id,
policyholders.firstname,
policyholders.lastname,
policyholders.city,
policyholders.state,
vehicles.yr,
vehicles.make,
vehicles.model,
vehicles.mileage,
clients.coname,
contracttypes.name,
coverageavailable.contractmonths,
contracts.contractwholesalecost,
contracts.begindate,
contracts.cancelledon,
contracts.paidon,
contracts.voided,
contracts.cancelledalphatotal)
GROUP BY contractid,
pholderid,
policyholdername,
policyholdercity,
policyholderstate,
vehicleyear,
vehiclemake,
vehiclemodel,
vehiclemileage,
clientname,
contracttype,
contractmonths,
wholesaleprice,
begindate,
cancelleddate,
cancelledalphatotal,
paiddate,
voided,
Iif(claimmileage > vehiclemileage, claimmileage, vehiclemileage)
ORDER BY clientname,
begindate DESC
希望一切,使得至少某種意義上...
...如果記錄在兩個數據集之間是唯一的,則可以使用UNION ALL加快速度(沒有ALL的UNION將取消延遲,並且即使在沒有重複時也會減慢速度)。 –
@David:謝謝你的建議。您似乎非常擅長Access(特定)。 – shahkalpesh