У меня есть страница на одном из веб-сайтов моего клиента, которая генерирует обширный отчет, извлекающий данные из многочисленных таблиц в базе данных веб-сайта 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
Надеюсь, все это имеет хоть какой-то смысл ...