Sum in Access Producing Total Sum and Placing This on Each Row - ms-access-2010

I am trying to create two columns: IntlAir and DomesticAir. I have a Boolean column in my data called International, and IntlAir returns Penalty + SellingFare when International is TRUE, and DomAir returns that sum when International = FALSE.
I would like to show this amount for each DK by Month.
My code is:
SELECT data.PostingMonth, data.DK_Number
, (SELECT sum(data.Penalty + data.SellingFare)
FROM data
WHERE data.International = TRUE) AS IntlAir
, (SELECT sum(data.Penalty + data.SellingFare)
FROM data
WHERE data.International = FALSE) AS DomesticAir
FROM data
GROUP BY data.PostingMonth, data.DK_Number
ORDER BY data.PostingMonth;
However, the output is giving me the total sum across all dks and across all months, and putting this value into every row.
Can someone tell me what I am doing wrong?

Perhaps this is all you need:
SELECT
PostingMonth,
DK_Number,
SUM((Penalty + SellingFare) * IIf(International, 1, 0)) AS IntlAir,
SUM((Penalty + SellingFare) * IIf(International, 0, 1)) AS DomAir
FROM [data]
GROUP BY PostingMonth, DK_Number
For the test data...
PostingMonth DK_Number International Penalty SellingFare
------------ --------- ------------- ------- -----------
1 1 False $10.00 $100.00
1 1 True $20.00 $200.00
2 1 False $30.00 $300.00
1 2 False $40.00 $400.00
1 2 False $50.00 $500.00
1 2 True $60.00 $600.00
...the above query returns
PostingMonth DK_Number IntlAir DomAir
------------ --------- ------- -------
1 1 $220.00 $110.00
1 2 $660.00 $990.00
2 1 $0.00 $330.00

There's a few ways to do that, though the one you chose wasn't one of them
Never sure where access is at in terms of sql but if you create a query that does this and call it queryAirTotal or somesuch
SELECT PostingMonth, DK_Number, International, sum(Penalty + SellingFare) as AirTotal
FROM data GROUP BY PostingMonth,DK_Number,International
That will give your totals by month, dk and type then you can do
Select t1.PostingMonth,t1.DK_Number,t1.AirTotal as IntlAir, t2.Total as DomesticAir
From queryAirTotal t1
Left Join queryAirTotal t2
On t1.PostingMonth = t2.PostingMonth and t1.DK_Number = t2.DK_Number
Where t1.International = TRUE and t2.International = FALSE
Though that will miss out Month/DKs where there was only Domestic air and no International air. You could sort that with a full outer join, which I believe access also struggles with.
You can get round that with a Union
Select t1.PostingMonth,t1.DK_Number,t1.AirTotal as IntlAir, t2.Total as DomesticAir
From queryAirTotal t1
Left Join queryAirTotal t2
On t1.PostingMonth = t2.PostingMonth and t1.DK_Number = t2.DK_Number
Where t1.International = TRUE and t2.International = FALSE
Union
Select t1.PostingMonth,t1.DK_Number,t1.AirTotal as IntlAir, t2.Total as DomesticAir
From queryAirTotal t1
Left Join queryAirTotal t2
On t2.PostingMonth = t1.PostingMonth and t2.DK_Number = t1.DK_Number
Where t1.International = TRUE and t2.International = FALSE

Related

Teradata: Sum Total Amount of Paid Claims by Duplicate DX Flag per Member

First, I'm sure there is a cleaner way to do this, but it's the only way I've been able to make the code combine the DX's into one column. Originally they were in separate columns as 0/1's and I needed them in one column. I tried the PIVOT function, but was not able to figure it out.
The issue is I need the paid amounts to be based on duplicated instances DX's. Which sounds counterintuitive, but for this report it's what I need.
For example. If member A has COPD, ASTHMA, AND DIABETES. The member's paid claims were 40,000 so I need the paid amount for that member to reflect 120,000, etc. and so forth.
The code:
SELECT
DX_FLAG
,Sum( AMT_PAID) AS PHARM_PAID_AMT
,Count(DISTINCT(MEMBER_AMISYS_NBR)) AS MEMBER_COUNT
FROM
(SELECT
st.MEMBER_AMISYS_NBR
,ph.PHARMACY_CLAIM_CK
,ph.AMT_PAID
,FILL.DATE_DATE AS Fill_Date
,Coalesce(CASE WHEN DX_ASTHMA = 'ASTHMA' THEN 'Asthma' END,
CASE WHEN DX_COPD = 'COPD' THEN 'COPD' END,
CASE WHEN DX_DIABETES = 'DIABETES' THEN 'DIABETES' END,
CASE WHEN DX_HEART_FAILURE = 'HEART FAILURE' THEN 'HEART_FAILURE' END,
CASE WHEN DX_HYPERTENSION = 'HYPERTENSION' THEN 'HYPERTENSION' END)
AS DX_FLAG
FROM
STATE_OVERALL_MBRS st
JOIN FT_PHARMACY_CLAIM ph ON st.MEMBER_CURR_CK = ph.PRESCRIBER_MEMBER_CURR_CK AND ph.DELETED_IND = 'N'
JOIN DIM_DATE FILL ON ph.FILL_DATE_DIM_CK = FILL.DATE_DIM_CK
WHERE FILL.DATE_DATE BETWEEN '2021-10-01' AND '2022-09-30'
AND ph.PLAN_DIM_CK =10
AND ph.REVERSAL_IND = 'N'
AND ph.AMT_PAID > 0
) rx
My output looks like this .
DX_FLAG
PHARM_PAID_AMT
MEMBER_COUNT
DIABETES
70,000,000
14,144
COPD
38,266,409
6,641
HEART_FAILURE
10,908,000
2,544
ASTHMA
125,000,000
30,000
HYPERTENSION
52,900
22,325
I have tried adding/removing the Distinct from each select statement and the only one that made a difference was removing distinct from this line, in which case I ended up with far too many member counts (even taking into account the duplicate DX counts).
,Count(DISTINCT(MEMBER_AMISYS_NBR)) AS MEMBER_COUNT
The State_Overall_Mbrs table with DX_Flag looks like this and I needed all the diagnosis to be in one column (with duplicate rows for members depending on how many diagnoses they have):
Member ID Asthma COPD Hypertension Diabetes CHF
55555555 0 1 1 1 0
66666666 1 0 0 1 0
77777777 0 0 1 0 0
Normalize the members table, then join and aggregate; something like this:
SELECT
DX_FLAG
,Sum(AMT_PAID) AS PHARM_PAID_AMT
,Count(DISTINCT(MEMBER_AMISYS_NBR)) AS MEMBER_COUNT
FROM
(SELECT * FROM State_Overall_Members
UNPIVOT (has_dx /* New column to hold the 0 or 1 value */
FOR DX_FLAG IN (Asthma,COPD,Hypertension,Diabetes,CHF)
/* Original column names become the values in new column DX_FLAG */
) nmlz
WHERE has_dx = 1 /* Only unpivot rows with a 1 in original column */
) st
JOIN FT_PHARMACY_CLAIM ph ON st.MEMBER_CURR_CK = ph.PRESCRIBER_MEMBER_CURR_CK AND ph.DELETED_IND = 'N'
JOIN DIM_DATE FILL ON ph.FILL_DATE_DIM_CK = FILL.DATE_DIM_CK
WHERE FILL.DATE_DATE BETWEEN '2021-10-01' AND '2022-09-30'
AND ph.PLAN_DIM_CK =10
AND ph.REVERSAL_IND = 'N'
AND ph.AMT_PAID > 0
GROUP BY DX_FLAG;
Another option to normalize the members table would be to have a subquery for each DX and UNION those, along these lines:
... FROM
(SELECT MEMBER_CURR_CK, MEMBER_AMISYS_NBR, AMT_PAID, 'Asthma' (VARCHAR(16)) AS DX_FLAG
FROM State_Overall_Members
WHERE Asthma = 1
UNION ALL
SELECT MEMBER_CURR_CK, MEMBER_AMISYS_NBR, AMT_PAID, 'COPD' (VARCHAR(16)) AS DX_FLAG
FROM State_Overall_Members
WHERE COPD = 1
UNION ALL
...
) st
JOIN ...

SQLite - Join returning duplicate result

I've read through dozens of posts on this so apologies if it's easily answered but I'm just not getting it.
Table Name: users
user_id group_id house_name
==========================================
923828395 1 Alpha
722161580 2 Beta
923828395 1 Gamma
Users can be in multiple Groups, and in a different House per Group.
Table Name: points
user_id group_id points term_id
=====================================================================================
722161580 1 18 02078e51
923828395 1 11 02078e51
923828395 2 140 81450fc1
Users can accumulate points in each Group they reside in. In the data above, user_id 923828395 exists in both group_id 1 and 2, accumulating points in both.
Query:
SELECT users.user_id, users.house_name, points.points, points.group_id, points.term_id
FROM users
JOIN points ON points.user_id = users.user_id
WHERE points.term_id = "02078e51" AND points.group_id = "1"
I'm trying to get this to just return 2 rows. However it's returning:
users.user_id users.house_name points.points points.group_id points.term_id
722161580 Beta 18 1 02078e51
923828395 Alpha 11 1 02078e51
923828395 Gamma 11 1 02078e51
I think this is because I've got something wrong with my WHERE .. I've tried flipping that to just an AND statement but I get the same results.
You should join the tables on group_id also:
SELECT u.user_id, u.house_name, p.points, p.group_id, p.term_id
FROM users u JOIN points p
ON p.user_id = u.user_id AND p.group_id = u.group_id
WHERE p.term_id = '02078e51' AND p.group_id = '1'
See the demo.

Why does COUNT return NULL instead of `0` in this query?

I have the query
select d.did, count ( h.did ), unique_interested
from dealer as d
left outer join house as h
on h.did = d.did
left outer join (
-- cid = customer id
select hid, count (cid) as unique_interested
from is_interested
group by hid
) as ok
on h.hid = ok.hid
group by d.did
order by d.did asc
;
which is supposed to select the number of houses that each dealer is dealing, and the number of unique customers interested in said houses (as in the number of customers per dealer). This should happen even if the dealers have no houses to deal at the moment, which is why I'm using left outer joins when constructing the table the columns will be picked from.
Now, running this query against my database produces the following output:
d.did count ( h.did) unique_interested
----- -------------- ----------------
1 3
2 3 1
3 0
As you can see, instead of printing 0 in the last column, count returns null, when there is a null in one of the aparments produced by the last part of the join (as in cid is null):
select hid, count ( cid ) as unique_interested
from is_interested
group by hid
I know this is because there are apartments in the table produced by from, that no-one is interested in. But shouldn't count produce 0 instead of the actual column value null in every case?
Any explanation as to why this is happening would be appreciated, as it would lead me towards an answer to another question, which is "Why am I not getting the right number of unique interested customers per dealer from the table is_interested?", as with the current state of my database, the output should look more like:
d.did count ( h.did) unique_interested
----- -------------- ----------------
1 3 2
2 3 2
3 0 0

Conditional selection of field values

I am working on a database created for sport games.
I have one table called game:
-----------------------------
winner | team_id1 | team_id2
-----------------------------
I have a table teams
----------
id | title
----------
if winner = 1, team_id1 is the id of the winner team
if winner = 2, team_id2 is the id of the winner team
At the end I want for each games to get the title of the winner team followed by the title of the loser team.
It tried something like:
select tea1.title, tea2.title
from games gam
join teams tea1 on case
when gam.winner = 1 and gam.team1_id = tea1.id then 1
when gam.winner = 2 and gam.team2_id = tea1.id then 1
else 0
end = 1
join teams tea2 on case
when gam.winner = 2 and gam.team1_id = tea2.id then 1
when gam.winner = 1 and gam.team2_id = tea2.id then 1
else 0
end = 1
But the request hangs, I don't understand why.
Try to get winner or loser title in select clause instead of join conditions.
select
gam.winner,
case when gam.winner=1 then t1.title else t2.title end as winner_title,
case when gam.winner=2 then t1.title else t2.title end as loser_title
from
games gam
left join
teams t1
on
gam.team1_id = t1.id
left join
teams t2
on
gam.team2_id = t2.id

Group by not returning 0 value

My table contains pk_id,reviewer_id,rating.
There are 4 type of rating.
1-very good.
2-good.
3-bad.
4-very bad.
I want to calculate how much rating given by each reviewer.
Means:
If Akee having id 200 has given 2 very good,4 good,3 bad and zero very bad rating to different code.
I want result
count--- rate
2---------1
4---------2
3---------3
0---------4
My query is
SELECT COUNT(RATE),RATE
FROM CODE_REVIEW WHERE CODE_REVIEWER_ID= 200
GROUP BY RATE;
It is showing result
count--- rate
2---------1
4---------2
3---------3
I want to show the fourth row that is 4 rating zero.
How can it be done??
If Rate is not the primary key in another table then you need define your own list of rates so MySQL knows what the permutations of rate are:
SELECT Rates.Rate,
COUNT(Code_Review.Rate) AS CountOfRate
FROM ( SELECT 1 AS Rate UNION ALL
SELECT 2 AS Rate UNION ALL
SELECT 3 AS Rate UNION ALL
SELECT 4
) AS Rates
LEFT JOIN Code_Review
ON Code_Review.Rate = Rates.Rate
AND CODE_REVIEWER_ID = 200
GROUP BY Rates.Rate
Try this query:
SELECT coalesce(c.cnt, 0), r.rate
FROM (SELECT 1 AS rate UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4) AS r
LEFT JOIN (SELECT COUNT(RATE),RATE
FROM CODE_REVIEW WHERE CODE_REVIEWER_ID= 200
GROUP BY RATE) AS c
ON r.rate = c.rate;
The first subquery creates a list of possible rates. You can avoid it if you have a table which defines all rates;
Second subquery is yours;
LEFT JOIN guarantees that all rates will be shown;
coalesce() is needed to convert NULL into 0.
Assuming that you do not have a separate table where the rates are defined.
SElECT * from (
SELECT distinct(m.rate), countrate from code_review m
LEFT JOIN
(SELECT COUNT(rate) as countrate,rate FROM code_review
WHERE code_reviewer_id=200 GROUP BY rate) t
ON m.rate=t.rate) a
You could do it somthing like this
SELECT
rates.RATE
, SUM(COUNT) COUNT
FROM
(
SELECT 1 RATE, 0 COUNT UNION ALL
SELECT 2 RATE, 0 COUNT UNION ALL
SELECT 3 RATE, 0 COUNT UNION ALL
SELECT 4 RATE, 0 COUNT
) Rates
LEFT JOIN
(
SELECT
RATE
, COUNT(RATE) COUNT
FROM
CODE_REVIEW
WHERE
CODE_REVIEWER_ID= 200
GROUP BY RATE
) Ratings200
ON Ratings200.RATE = Rates.RATE
If you can, you should push to try to get it in column format as it is simple as:
SELECT
SUM(rate = 1) AS 1,
SUM(rate = 2) AS 2,
SUM(rate = 3) AS 3,
SUM(rate = 4) AS 4
FROM
code_review
WHERE
code_reviewer_id = 200
But if you really need a row format, you could do:
SELECT
a.rate,
COUNT(b.rate) AS cnt
FROM
(
SELECT 1 AS rate UNION ALL
SELECT 2 AS rate UNION ALL
SELECT 3 AS rate UNION ALL
SELECT 4 AS rate
) a
LEFT JOIN
code_review b ON a.rate = b.rate AND code_reviewer_id = 200
GROUP BY
a.rate
SELECT
Rate,
totCount
FROM
(
Select
Rate,
count(Rate) as totCount
from
Code_Review
where
CODE_REVIEWER_ID = 200
group by
Rate
union
select 4, 0
union
select 3, 0
union
select 2, 0
union
select 1, 0
) AS T
group by
T.Rate

Resources