I have a small challenge trying to create a "work in progress view"
I'm not convinced my statement is the best or correct and resulted in an error "Subquery returned more than 1 value"
I have three key tables;
Tasks
PurchaseOrderItem
Resource
There is a unique reference field across all the tables e.g. Tasks.TA_SEQ, PurchaseOrderItem.TA_SEQ and Resource.TA_SEQ
I need to sum different totals from all these tables and the relationship are as follows;
1 Task - many PurchaseOrderItem
1 Task - many Resources
I need to sum all the Purchase order cost values (line items can vary) against active purchase orders for the Task and also sum all the resource cost (3 people - quantity can vary) against the task, any help would be much appreciated. if I can make it also any easier any advice would be appreciated.
Part of my Query as it stands;
SELECT
dbo.F_TASKS.TA_SEQ,
(
SELECT
SUM(POI_TOTAL)
From F_PO_ITEM
where POI_FKEY_TA_SEQ = dbo.F_TASKS.TA_SEQ
and POI_FKEY_POH_SEQ in
(
select
POH_SEQ
from F_PO_HEAD
where POH_STATUS in ('DORMANT', 'ACTIVE')
)
) AS [Pending PO Cost],
dbo.F_TASKS.TA_PO_COST AS [PO Cost],
dbo.F_TASKS.TA_LABOUR_COST AS [Labour Cost],
dbo.F_TASKS.TA_LABOUR_COST - SUM(dbo.F_TASK_TIME.TT_OTHER_COSTS) AS [New Labour Cost],
-----------Not Working from
(select
SUM(dbo.F_TASK_TIME.TT_OTHER_COSTS)
from F_TASK_TIME
where TT_FKEY_TA_SEQ = dbo.F_TASKS.TA_SEQ) + dbo.F_TASKS.TA_PO_COST AS [Subcontractor Costs],
(SUM(dbo.F_TASK_TIME.TT_OTHER_COSTS + dbo.F_TASKS.TA_PO_COST)) * 0.12 AS [Subcontractor Uplift],
((SUM(dbo.F_TASK_TIME.TT_OTHER_COSTS + dbo.F_TASKS.TA_PO_COST)) * 0.12) + (SUM(dbo.F_TASK_TIME.TT_OTHER_COSTS + dbo.F_TASKS.TA_PO_COST)) AS [Subcontractor Uplift Total]
-----------Not Working To
FROM dbo.F_TASKS
LEFT OUTER JOIN dbo.F_TASK_TIME
ON dbo.F_TASKS.TA_SEQ = dbo.F_TASK_TIME.TT_FKEY_TA_SEQ
LEFT OUTER JOIN dbo.F_PO_ITEM
ON dbo.F_TASKS.TA_SEQ = dbo.F_PO_ITEM.POI_FKEY_TA_SEQ
WHERE (dbo.F_TASKS.TA_TASK_DESC = 'BREAKDOWN')
AND (dbo.F_TASKS.TA_PO_COST >= 0)
AND (dbo.F_TASKS.TA_STATUS IN ('ACTIVE', 'ASSIGNED', 'COMPLETE'))
GROUP BY dbo.F_TASKS.TA_PO_COST, dbo.F_TASKS.TA_SEQ, dbo.F_TASKS.TA_LABOUR_COST
Rather than trying to fix your SQL, I'm going to propose a different wau of doing it. I couldn';t easily understand all the wheres in your selects in the select clause, so I've just done the first two.
This approach uses LEFT OUTER JOINs to queries which total by ta_seq. These are guaranteed to return only one row/ta_seq as that's how there're grouped:
SELECT
t.TA_SEQ,
isnull(po.poi_total, 0) [Pending PO Cost],
t.TA_PO_COST AS [PO Cost],
t.TA_LABOUR_COST AS [Labour Cost],
t.TA_LABOUR_COST - isnull(tt.other_costs, 0) AS [New Labour Cost],
-- other cols missed
FROM dbo.F_TASKS t
left outer join
(
t.ta_seq, SUM(POI_TOTAL) poi_total
From F_PO_ITEM poi
where POI_FKEY_POH_SEQ in
(
select
POH_SEQ
from F_PO_HEAD
where POH_STATUS in ('DORMANT', 'ACTIVE')
)
group by t.ta_seq
) po on po.ta_seq = t.ta_seq
left outer join
(
select tt.TT_FKEY_TA_SEQ ta_seq, sum(tt.tt_other_costs) other_costs
from F_TASK_TIME tt
group by tt.TT_FKEY_TA_SEQ
) tt on tt.ta_seq = t.ta_seq
WHERE (t.TA_TASK_DESC = 'BREAKDOWN')
AND (t.TA_PO_COST >= 0)
AND (t.TA_STATUS IN ('ACTIVE', 'ASSIGNED', 'COMPLETE'))
GROUP BY t.TA_PO_COST, t.TA_SEQ, t.TA_LABOUR_COST
I've also used table aliases as I find the schema.tablename format is making me blind (and not helping me decode the missed subqueries).
To put in the missing columns, just translate them into additional LEFT OUTER JOINs as above.
Cheers -
Related
I'm looking for a way to create an Access crosstab query reporting sales totals by 'Brand', for two different date ranges.:
For Distributor: "DistID" (column, not visible)
Sales Totals: "Sales" (column)
TWO different date ranges: "depDate" for Period 1 and Period 2 (column):
Period1 = Between [forms]![frmRPT_YTDDepl_SF]![BDT1] And [forms]![frmRPT_YTDDepl_SF]![EDT1]
Period2 = Between [forms]![frmRPT_YTDDepl_SF]![BDT2] And [forms]![frmRPT_YTDDepl_SF]![EDT2]
Brands = "DprodBrand" (rows)
Currently, I have TWO separate crosstab queries for each period, working properly. -> CODE BELOW.
I am looking for a way to create ONE query displaying Brand's sales totals for each date range, in two separate columns or one crosstab query.
Period1:
TRANSFORM Sum(tblDepletions_DETAIL.detQuan) AS Sales
SELECT tblProducts_DEPL.DprodBrand
FROM tblDepletions INNER JOIN (tblProducts_DEPL INNER JOIN tblDepletions_DETAIL ON tblProducts_DEPL.DprodZSKU = tblDepletions_DETAIL.detZSKU) ON tblDepletions.depID = tblDepletions_DETAIL.detDeplID
WHERE (((tblDepletions.depDate) Between [forms]![frmRPT_YTDDepl_SF]![BDT1] And [forms]![frmRPT_YTDDepl_SF]![EDT1]) AND ((tblDepletions.depDistID)=132))
GROUP BY tblProducts_DEPL.DprodBrand
ORDER BY tblProducts_DEPL.DprodBrand
PIVOT Format([depDate],"yy")-(Format(Date(),"yy"))+2 In (1,2);
Period2:
TRANSFORM Sum(tblDepletions_DETAIL.detQuan) AS Sales
SELECT tblProducts_DEPL.DprodBrand
FROM tblDepletions INNER JOIN (tblProducts_DEPL INNER JOIN tblDepletions_DETAIL ON tblProducts_DEPL.DprodZSKU = tblDepletions_DETAIL.detZSKU) ON tblDepletions.depID = tblDepletions_DETAIL.detDeplID
WHERE (((tblDepletions.depDate) Between [forms]![frmRPT_YTDDepl_SF]![BDT2] And [forms]![frmRPT_YTDDepl_SF]![EDT2]) AND ((tblDepletions.depDistID)=132))
GROUP BY tblProducts_DEPL.DprodBrand
ORDER BY tblProducts_DEPL.DprodBrand
PIVOT Format([depDate],"yy")-(Format(Date(),"yy"))+2 In (1,2);
Many Thanks!!! ~~ Jacob
Consider simply joining the two saved, crosstab queries like any other pair of queries or tables using the DprodBrand as join key:
SELECT CrosstabQ1.DprodBrand,
CrosstabQ1.[1] As Period1_Year1, CrosstabQ2.[1] As Period2_Year1,
CrosstabQ1.[2] As Period1_Year2, CrosstabQ2.[2] As Period2_Year2
FROM CrosstabQ1
INNER JOIN CrosstabQ2 ON CrosstabQ1.DprodBrand = CrosstabQ2.DprodBrand
Now if you only want one query to do it all, consider the conditional aggregate pivot query since crosstabs cannot be used as subqueries. Here you migrate WHERE to IIF() conditions:
SELECT p.DprodBrand,
SUM(IIF((d.depDate BETWEEN [Forms]![frmRPT_YTDDepl_SF]![BDT1]
AND [Forms]![frmRPT_YTDDepl_SF]![EDT1])
AND (Format(d.[depDate],"yy")-(Format(Date(),"yy"))+2 = 1),
dt.detQuan, NULL)) AS Period1_Year1,
SUM(IIF((d.depDate BETWEEN [Forms]![frmRPT_YTDDepl_SF]![BDT2]
AND [Forms]![frmRPT_YTDDepl_SF]![EDT2)
AND (Format(d.[depDate],"yy")-(Format(Date(),"yy"))+2 = 1),
dt.detQuan, NULL)) AS Period2_Year1,
SUM(IIF((d.depDate BETWEEN [Forms]![frmRPT_YTDDepl_SF]![BDT1]
AND [Forms]![frmRPT_YTDDepl_SF]![EDT1])
AND (Format(d.[depDate],"yy")-(Format(Date(),"yy"))+2 = 2),
dt.detQuan, NULL)) AS Period1_Year2,
SUM(IIF((d.depDate BETWEEN [Forms]![frmRPT_YTDDepl_SF]![BDT2]
AND [Forms]![frmRPT_YTDDepl_SF]![EDT2])
AND (Format(d.[depDate],"yy")-(Format(Date(),"yy"))+2 = 2),
dt.detQuan, NULL)) AS Period2_Year2
FROM tblDepletions d
INNER JOIN (tblProducts_DEPL p
INNER JOIN tblDepletions_DETAIL dt
ON p.DprodZSKU = dt.detZSKU)
ON d.depID = dt.detDeplID
WHERE ((d.depDistID)=132)
GROUP BY p.DprodBrand
ORDER BY p.DprodBrand
As this is Access, it might be simpler to save the two queries leaving out the ORDER BY.
Then create a new query:
SELECT *
FROM Q1
UNION ALL
SELECT *
FROM Q2
ORDER BY DprodBrand
By: Dale Fye (Access MVP):
I'm not sure you need a CrossTab for this.
Select DProdBrand,
SUM(IIF([DepDate] BETWEEN [Forms]![frmRpt_YTDDepl_SF]![BDT1]
AND [[forms]![frmRPT_YTDDepl_SF]![EDT1], [Sales], 0) as Period1,
SUM(IIF([DepDate] Between [forms]![frmRPT_YTDDepl_SF]![BDT2]
AND [forms]![frmRPT_YTDDepl_SF]![EDT2], [Sales], 0) as Period2,
SUM([Sales]) as [Sales Total]
FROM yourTable
GROUP BY DProdBrand
https://www.experts-exchange.com/questions/28978325/Access-Crosstab-Query-based-on-sales-totals-within-TWO-date-ranges.html
I'm working on a comparison query that will compare what was processed for the different credit card types versus what was actually processed by our POS service. I have ran into an issue where I am not seeing rows for certain card types if they did not process any payments on a given day but may have given a refund. IE: Nothing purchased with VISA but a VISA refund was given, but due to no purchases the row does not show up even though there's a refund for that type.
Here is my query:
WITH tran_total AS (
SELECT CONCAT(c.id_str, ' - ', c.clinic_str) AS Clinics,
t.clinic,
c.xcharge_mid,
p.pay_desc,
CAST(t.time_ran AS date) AS tran_date,
CASE WHEN SUM(t.amount) <> 0 THEN SUM(t.amount) * - 1
ELSE 0.00 END AS collection
FROM dbo.transactions AS t INNER JOIN
dbo.clinic_master AS c ON t.clinic = c.clinic INNER JOIN
dbo.paytype AS p ON t.clinic = p.clinic AND t.paytype_id = p.paytype_id
WHERE (t.time_ran > GETDATE() - 10)
AND (t.paytype_id IS NOT NULL)
AND (p.pay_desc = 'Visa' OR
p.pay_desc = 'MasterCard' OR
p.pay_desc = 'American Express' OR
p.pay_desc = 'Discover')
GROUP BY c.id_str, c.clinic_str, t.clinic, c.xcharge_mid, p.pay_desc, CAST(t.time_ran AS date))
SELECT w.Clinics,
w.pay_desc,
w.tran_date,
w.collection,
CASE WHEN w.pay_desc = 'Visa' THEN (SUM(VI_pur) - SUM(VI_ref))
WHEN w.pay_desc = 'MasterCard' THEN (SUM(MC_pur) - SUM(MC_ref))
WHEN w.pay_desc = 'American Express' THEN (SUM(AX_pur) - SUM(AX_ref))
WHEN w.pay_desc = 'Discover' THEN (SUM(DI_pur) - SUM(DI_ref)) END AS xcharge
FROM tran_total AS w LEFT OUTER JOIN
dbo.xcharge AS x ON w.xcharge_mid = x.xcharge_mid AND w.tran_date = x.settle_date
GROUP BY w.Clinics, w.pay_desc, w.tran_date, w.collection
ORDER BY w.Clinics, w.tran_date
I've thought about switching this around and starting with the comparison from the xcharge table but there is not a pay_desc that links those easily and if something is processed as the wrong card (VISA is chosen but Discover is scanned) then I feel the rows would be missed still.
What I would like, is for all of the pay_desc to show up for each tran_date even if the SUM(t.amount) does not have a value. I've tried a case statement to accomplish this without any luck.
EDIT: I feel the issue is more due to the t.time_ran variable. If there isn't a payment for a given pay_desc then there won't be a t.time_ran either, is there a function I can do to list out dates between GETDATE()-10 AND GETDATE() kind of thing and just have the t.time_ran and x.settle_date match up to that variable instead?
Any thoughts on this? Thanks in advance
UPDATE:
I have created a calendar table with individual dates and have tried the following query:
WITH tran_test AS(
SELECT cal.calendardate AS cd,
p.clinic,
p.pay_desc,
p.paytype_id
FROM calendar cal, paytype p
WHERE cal.calendardate BETWEEN GETDATE()-10 AND GETDATE()+1
AND (p.pay_desc = 'Visa' OR
p.pay_desc = 'MasterCard' OR
p.pay_desc = 'American Express' OR
p.pay_desc = 'Discover'))
SELECT w.cd,
CONCAT(c.id_str, ' - ', c.clinic_str) AS Clinics,
w.pay_desc,
ISNULL(SUM(t.amount)*-1, 0) AS collection,
CASE WHEN w.pay_desc = 'Visa' THEN (SUM(x.VI_pur) - SUM(x.VI_ref))
WHEN w.pay_desc = 'MasterCard' THEN (SUM(x.MC_pur) - SUM(x.MC_ref))
WHEN w.pay_desc = 'American Express' THEN (SUM(x.AX_pur) - SUM(x.AX_ref))
WHEN w.pay_desc = 'Discover' THEN (SUM(x.DI_pur) - SUM(x.DI_ref)) END AS xcharge
FROM tran_test w
INNER JOIN clinic_master c
ON (w.clinic=c.clinic)
LEFT OUTER JOIN transactions t
ON (t.clinic=w.clinic AND t.paytype_id=w.paytype_id AND CAST(t.time_ran AS date) = w.cd)
LEFT OUTER JOIN xcharge x
ON (w.cd=x.settle_date AND c.xcharge_mid=x.xcharge_mid)
GROUP BY w.cd, c.id_str, c.clinic_str, w.pay_desc
ORDER BY w.cd
However, I'm not getting an issue where my xcharge column seems to multiplying itself by random intervals and I'm not sure why.
It sounds like what you need is a Calendar table. You can generate one as part of a CTE (many examples on this site or just search Google), but IMO you should have a persistent table in your database. This way you can mark certain days as bank holidays, what quarter your business considers them to be in, etc.
Once you have that table in place you can SELECT your dates from that table and then LEFT OUTER JOIN to that table from your Transactions table. Any dates without matching rows in Transactions will still show up with a row, but you'll have 0.00 value for your SUM.
I'm currently struggling with a (at least for me) pretty complex SQL query.
I'm trying to calculate commissions.
To calculate properly I need to subtract credits from invoices. As there is no direct relationship between invoices and corresponding credits, I'm joining over their positions.
Anyways, I'd like to display each Invoice (and its creditMemo) only once.
DISTINCT however doesn't work here due to the join with the positions (I guess).
So how could I achieve a clean list of all invoices including their creditmemos (if exists) only once each?
I know of the GROUP BY clause. I can not manage to use it without losing accurate invoice values due to missing positions...
Any idea how to manage this case?
(removed unnecessary information)
SELECT DISTINCT
R.DocNum as InvoiceNo,
R.DocDate as Date,
R.CardCode as BusinessPartnerID,
R.CardName as BusinessPartnerName,
R.DocTotal as wVat,
(R.DocTotal - R.VatSum) as NoVat,
SUM(R1.LineTotal) OVER () as R_NoVatAll,
SUM(R1.LineTotal) OVER () + SUM(R1.VatSum) OVER () AS wVatAll,
R.GrosProfit as Gross,
SUM(R1.GrssProfit) OVER () AS GrossAll,
R.VatSum as VatSum,
G.DocNum as G_Gutschriftnummer,
G.DocDate as G_Datum,
G.DocTotal as G_wVat,
(G.DocTotal - G.VatSum) as G_NoVat,
SUM(-G1.LineTotal) OVER () AS G_noVatAll,
SUM(-G1.GrssProfit) OVER () AS G_grossAll,
-G.VatSum as G_Ust,
V.slpName as slpName,
V.Commission as Commission,
(ISNULL(V.Commission,8)/100*R1.GrssProfit) as CommissionValue, (ISNULL(V.Commission,8)/100*-(G1.GrssProfit + G1.VatSum) ) as CommissionValueMinus,
(SUM(-(G1.LineTotal )) OVER()) as CreditAll,
(SUM(R1.GrssProfit) OVER () - SUM(G1.GrssProfit) OVER ()) as CommissionBase,
(SUM(R1.GrssProfit) OVER () - SUM(G1.GrssProfit) OVER ()) * 8/100 as CommissionTotal
FROM OINV R -- Invoices
INNER JOIN INV1 R1 ON R.DocEntry = R1.DocEntry -- InvoicePositions
LEFT JOIN RIN1 G1 ON G1.BaseEntry = R1.DocEntry AND G1.BaseLine = R1.LineNum AND G1.BaseType = 13 -- CreditPositions
FULL JOIN ORIN G ON G1.DocEntry = G.DocEntry -- Credits
LEFT JOIN OSLP V ON G.slpCode = V.slpCode -- SLPs
WHERE 1=1
AND (R.DocDate BETWEEN '07.01.2015' AND '07.31.2015' OR G.DocDate BETWEEN '07.01.2015' AND '07.31.2015')
AND R1.AcctCode <> '9085'
AND R.DocTotal <> 0
AND R.CANCELED <> 'Y'
AND G.DocTotal <> 0
ORDER BY R.DocNum
I have an Access DB I am maintaining for a client.
I have 4 tables. Claims, Eligibility, Pharmacy, and Codes.
The Primary Key I am using is PHID + SID = MemberID which I am linking to each table, and then the Codes table is merely used for a description. See queries below for better visualization of that...
Query 1: Member_Claims_Query
SELECT
Eligibility.GROUPID,
Eligibility.PHID & '-' & Eligibility.SID AS MemberID,
[Eligibility].[DOB] AS DOB,
Eligibility.GENDER,
Eligibility.RELATIONSHIP_CODE,
MaxDiagDollars.HighestDiagPaid/SUM(Claims.PAID_AMT) AS ['%'],
MaxDiagDollars.HighestDiagPaid/SUM(Claims.PAID_AMT) as 'Percent',
ROUND(SUM(Claims.PAID_AMT)) AS TOTALPAID,
ROUND(Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2011',Claims.PAID_AMT,0))) AS 2011TOTALPAID,
ROUND(Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2012',Claims.PAID_AMT,0))) AS 2012TOTALPAID,
ROUND(Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2013',Claims.PAID_AMT,0))) AS 2013TOTALPAID
FROM (Claims
INNER JOIN Eligibility
ON (Claims.[SID] = Eligibility.[SID]) AND (Claims.[PHID] = Eligibility.[PHID]))
INNER JOIN (SELECT PHID, SID, MAX(TotalPaid) AS HighestDiagPaid
FROM (SELECT [PHID], [SID], DIAG_CODE1, SUM(PAID_AMT) AS TotalPaid FROM Claims GROUP BY [PHID], [SID], [DIAG_CODE1]) AS [%$###_Alias] GROUP BY PHID, SID) AS MaxDiagDollars ON ( MaxDiagDollars.[PHID]=Eligibility.[PHID] ) AND ( MaxDiagDollars.[SID] = Eligibility.[SID] )
WHERE Eligibility.DOB < DateAdd( 'y', -2, DATE())
GROUP BY
Eligibility.GROUPID, Eligibility.PHID & '-' & Eligibility.SID, [Eligibility].[DOB], Eligibility.GENDER, Eligibility.RELATIONSHIP_CODE, MaxDiagDollars.HighestDiagPaid
HAVING SUM(Claims.PAID_AMT)>10000 and MaxDiagDollars.HighestDiagPaid/SUM(Claims.PAID_AMT) <= 0.80;
This query is supposed to take the Total Amount Paid per Member and give a Total Amount PAid, and then yearly break outs.
Query 2: Member_By_Diag
SELECT
Eligibility.PHID & '-' & Eligibility.SID AS MemberID,
Claims.Diag_Code1,
ROUND(Sum(Claims.PAID_AMT)) AS TotalPaid,
ROUND(Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2011',Claims.PAID_AMT,0))) AS 2011TotalPaid,
ROUND(Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2012',Claims.PAID_AMT,0))) AS 2012TotalPaid,
ROUND( Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2013',Claims.PAID_AMT,0))) AS 2013TotalPaid
FROM
(Claims
INNER JOIN Eligibility
ON (Claims.[SID] = Eligibility.[SID]) AND (Claims.[PHID] = Eligibility.[PHID]))
INNER JOIN Pharmacy
ON (Eligibility.SID = Pharmacy.SID) AND (Eligibility.PHID = Pharmacy.PHID)
GROUP BY
Eligibility.PHID & '-' & Eligibility.SID, Claims.Diag_Code1
HAVING count( [Pharmacy].[NDC] ) >4 and count(IIF(Claims.REV_CODE= '450',1,0) ) > 1
ORDER BY Eligibility.PHID & '-' & Eligibility.SID;
The second query is essentially supposed to take the Codes for each member and break out their amount paids by Diagnosis code.
Query 3: combined_query
SELECT *
FROM (Member_Claims_Query AS a INNER JOIN Member_by_Diag AS b ON a.MemberID=b.MemberID) INNER JOIN Codes AS c ON c.DxCode = b.Diag_Code1;
ISSUE
My Client sent me an e-mail stating that the Total Paid in the Member_By_Diag query is sometimes higher than the Total Paid by the Member_By_Claim query. yet they are being computed the same way.
I opened up the DB and wrote a simple query to see how many records were returning where the b.Total_Paid ( Member_By_Diag.Total_Paid) is greater than the Member_Claims_Query.Total_Paid.
It returned 262/1278 records where this was the case.
SELECT * FROM Combined_Query WHERE b_TotalPaid > a_TotalPaid
This picture acurately describes what I am seeing along with my client.
As you can see. a_TotalPaid > b_TotalPaid. But if you look up at my query, they are the same? Is this a group by issue? or a join issue? Any help would be much appreciated.
There are a couple of differences between the queries that could be contributing to this. The main culprits are your INNER JOIN statements and your HAVING statement. Those could easily be excluding records that will have an effect on your TotalPaid field. Without the original dataset, there's not much I can tell you, but you may want to run those queries and play with removing and inserting the various INNER JOIN and HAVING clauses to see which one is deleting the records that are causing your totals to not be equal.
I appreciate the answers everyone... You didn't exactly answer the question, but the inner join on Pharmacy was causing the issue, I was specifically using it in relation to the HAVING clause, when I added a count(*) I noticed it was actually multiplying my results. For Ex. If a member had 7 claims, and 6 Pharmacy records it was multiplying it making it 42 records making my total paids extremely high, and they weren't relating to the CLAIMS themselves...hence the ultimate issue. Here is the solution in the Member_By_Diag Query:
SELECT Eligibility.PHID & '-' & Eligibility.SID AS MemberID, Claims.Diag_Code1, Round(Sum(Claims.PAID_AMT)) AS TotalPaid, Round(Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2011',Claims.PAID_AMT,0))) AS 2011TotalPaid, Round(Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2012',Claims.PAID_AMT,0))) AS 2012TotalPaid, Round(Sum(IIf(Format(Serv_Beg_Date,'yyyy')='2013',Claims.PAID_AMT,0))) AS 2013TotalPaid, Count(*) AS Expr1
FROM (Claims INNER JOIN Eligibility ON (Claims.[SID] = Eligibility.[SID]) AND (Claims.[PHID] = Eligibility.[PHID])) INNER JOIN ***(SELECT PHID, SID, COUNT(NDC) AS RXCount FROM Pharmacy GROUP BY PHID, SID ORDER BY PHID, SID) AS Pharmacy*** ON (Eligibility.SID = Pharmacy.SID) AND (Eligibility.PHID = Pharmacy.PHID)
GROUP BY Eligibility.PHID & '-' & Eligibility.SID, Claims.Diag_Code1
***HAVING Count(IIf([Claims].[REV_CODE]='450',1,0))>1***
ORDER BY Eligibility.PHID & '-' & Eligibility.SID;
This made the dollars look much more reasonable. Thanks everyone.
I have a page in one of my client's websites that generates an extensive report pulling data from numerous tables throughout the website's MS Access database. One of the unfortunate architectural issues of the website is the existence of two nearly identical tables that represent the same "type" of data, but one is an "old" version and the other is a "new" version. When the report is generated I need to perform some aggregate operations on the two similar tables. The initial query joined these tables into the rest of the data and called the appropriate aggregate functions on the joined tables. Soon I realized that a join would not work because the two tables do not necessarily have the same row count, thus causing the aggregate function to improperly group the rows from both tables...
Were this MSSQL or MySQL I would probably create a VIEW containing the composite data from both tables, but unfortunately I'm stuck in MS Access where such "novel" concepts do not exist... The solution I was able to come up with works, but has got to be some of the ugliest SQL I have ever seen. Basically, I create a SQL query including all of the appropriate columns from multiple joined tables and one of the two similar tables. Then I create a second SQL query containing all of the same fields and join the other similar table. Finally, I UNION the two queries and wrap them into a subquery within the FROM clause of an outer query.
The end result is a massive query with a ton of duplicate selects that I included only because of the need to aggregate data from the two similar tables. I really would like to refactor the query into something less awful, but I'm not sure where to start... Any advice?
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
Hopefully all that makes at least some sense...
QueryDef in Access, is similar to a VIEW in other RDBMS.
Based on the first glance, it is better to get the UNION part of the query in a querydef.