MS Access - 查询重构帮助

时间:2009-09-01 03:16:52

标签: sql ms-access refactoring

我在我的一个客户网站上有一个页面,它生成一个广泛的报告,从整个网站的MS Access数据库中的众多表中提取数据。网站的一个不幸的架构问题是存在两个几乎相同的表,它们代表相同的“类型”数据,但一个是“旧”版本,另一个是“新”版本。生成报告时,我需要对两个类似的表执行一些聚合操作。初始查询将这些表连接到其余数据中,并在连接表上调用适当的聚合函数。很快我意识到连接不起作用,因为这两个表不一定具有相同的行数,从而导致聚合函数不正确地对两个表中的行进行分组......

如果这个MSSQL或MySQL我可能会创建一个包含来自两个表的复合数据的VIEW,但不幸的是我被困在MS Access中,这样的“新颖”概念不存在......解决方案我能够来与作品,但必须是我见过的最丑陋的SQL。基本上,我创建了一个SQL查询,包括来自多个连接表的所有相应列以及两个相似表中的一个。然后我创建一个包含所有相同字段的第二个SQL查询,并加入另一个类似的表。最后,我UNION两个查询并将它们包装到外部查询的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

希望这一切至少在某种意义上......

1 个答案:

答案 0 :(得分:3)

Access中的QueryDef类似于其他RDBMS中的VIEW 基于第一眼,最好在querydef中获取查询的UNION部分。