SumIF in SQL Access - sql

Hello I am a beginner in VBA/SQL. I have 2 tables [Broker] and [OPT]. [Broker] have 2 fields BRKR_CODE, Status and [OPT] Have 5 fields BRKR1, BRKR2, Date, COM_BRK1, COM_BRKR2
OPT.BRKR1 and OPT.BRKR2 are linked to Broker.BRKR_CODE and can be equal.
I want to write this query.... If Broker.Status="Active" then Select Broker.BRKR_CODE
and then for each Broker.BRKR_CODE (for example "CB") do the Sum of OPT.COM_BRKR1 when OPT.BRKR1="CB" + Sum of OPT.COM_BRKR2 when OPT.BRKR2="CB"
I wrote this code.... but it doesnot work at all... as I said I am a newbie...
SELECT IIF(Broker.Status="Active",Broker.BRKR_CODE), Sum(OPT.COM_BRKR1)+ Sum(OPT.COM_BRKR2) AS OPT_Tot
FROM Broker INNER JOIN OPT ON (Broker.BRKR_CODE = OPT.BRKR2) AND (Broker.BRKR_CODE = OPT.BRKR1)
GROUP BY Broker.BRKR_CODE;
Thanks a lot

If I understand correctly, you need to change two things in your query. The first is to move the condition to the where clause. You seem to only want "Active" things. The second is to change the AND in the on clause to OR. You want matches on either code.
SELECT Broker.BRKR_CODE,
Sum(OPT.COM_BRKR1)+ Sum(OPT.COM_BRKR2) AS OPT_Tot
FROM Broker INNER JOIN
OPT
ON (Broker.BRKR_CODE = OPT.BRKR2) OR (Broker.BRKR_CODE = OPT.BRKR1)
WHERE Broker.Status = "Active"
GROUP BY Broker.BRKR_CODE;

Related

Finding differences in queries using two criteria

I'm trying to find a way to find a way to compare two queries that use a combine sent of criteria. In this case we have Prefixes (Two letter code like DA) and Pack number 1234567. In the query I've created a field that combines these two things so it appears 1234567DA this is done with each of the queries from the separate tables they are pulled from. The idea is that if this is in one table and not the other it would show up as "False". I tried to use an Unmatched query but that doesn't seem to work. What I have currently is as follows:
SELECT
[1LagoTest].Prefix,
[1BigPicPackPref].BigPicPP,
IIf([BigPicPP]=[LagoPP],"True","False") AS Compare,
[1LagoTest].RETAIL,
[1LagoTest].MEDIA
FROM 1LagoTest
LEFT JOIN 1BigPicPackPref
ON [1LagoTest].[Prefix] = [1BigPicPackPref].[BigPicPP]
WHERE (((IIf([BigPicPP]=[LagoPP],"True","False")) Like "False")
AND (([1LagoTest].MEDIA) Not Like "*2019 FL*"))
ORDER BY [1LagoTest].RETAIL;
Right now it will show whats missing from LagoPP but doesn't give me anything from missing packs in BigPicPP. Any help in the right direction would be greatly appreciated.
Thanks!!
This gets a little tricky in Access without FULL OUTER JOIN, but the general idea to is replicate a FULL OUTER JOIN using UNION ALL, then filter from that.
Something like this:
SELECT I.Prefix,
I.BigPicPP,
I.Compare,
I.Retail,
I.Media
FROM (SELECT L.Prefix,
B.BigPicPP,
IIf([BigPicPP]=[LagoPP],"True","False") as Compare,
L.Retail,
L.Media
FROM 1LagoTest L
JOIN 1BigPicPackPref B ON L.Prefix = B.BigPicPP
WHERE L.Media NOT LIKE "*2019 FL*"
UNION ALL
SELECT L.Prefix,
B.BigPicPP,
"False", --Missing records from 1BigPicPackPref
L.Retail,
L.Media
FROM 1LagoTest L
LEFT JOIN 1BigPicPackPref B ON L.Prefix = B.BigPicPP
AND L.Media NOT LIKE "*2019 FL*"
WHERE B.Prefix IS NULL
UNION ALL
SELECT B.Prefix,
B.BigPicPP,
"False", --Missing records from 1LagoTest
L.Retail,
L.Media
FROM 1LagoTest L
RIGHT JOIN 1BigPicPackPref B ON L.Prefix = B.BigPicPP
AND L.Media NOT LIKE "*2019 FL*"
WHERE L.Prefix IS NULL
) AS I
You only need IFF in the first part of the union because in the second two parts one side will always be NULL, so we know the compare will always fail and be False.
You shouldn't need this part of your current WHERE clause at all (((IIf([BigPicPP]=[LagoPP],"True","False")) Like "False"). But if you only want to see False records, just add WHERE I.Compare = "False" to the bottom of the outer select.
The reason the "Unmatched" query (assuming through the Wizard) does not work, is because you are attempting to see the values of two separate tables / queries that do not match either table / query. This is not how the "Unmatched" works. All that will give you is a single table / query that does not match another single table / query.
This can most likely be done any number of ways, but this would probably get you where you want to be (or close to it):
SELECT
a.Prefix,
b.BigPicPP,
IIf([BigPicPP]=[LagoPP],"True","False") AS Compare,
a.RETAIL,
a.MEDIA
FROM [1LagoTest] a
LEFT JOIN [1BigPicPackPref] b ON a.Prefix = b.BigPicPP
WHERE a.MEDIA Not Like "*2019 FL*"
AND b.BigPicPP IS NULL
ORDER BY a.RETAIL
UNION
SELECT
a.Prefix,
b.BigPicPP,
IIf([BigPicPP]=[LagoPP],"True","False") AS Compare,
a.RETAIL,
a.MEDIA
FROM [1LagoTest] a
RIGHT JOIN [1BigPicPackPref] b ON a.Prefix = b.BigPicPP
WHERE a.MEDIA Not Like "*2019 FL*"
AND a.Prefix IS NULL
ORDER BY a.RETAIL
NOTE: Depending on the data structure, the ORDER BY may cause some issues.
So the way I got this to finally work was to build two separate queries. One looking at what was missing from Lago and One that was looking at what was missing from BigPic. It was the only way I could get it to give me both sets of missing data. If I can find a better way to do it through one query I will report back as I'm still gonna play around with it.

How can I do a SQL join to get a value 4 tables farther from the value provided?

My title is probably not very clear, so I made a little schema to explain what I'm trying to achieve. The xxxx_uid labels are foreign keys linking two tables.
Goal: Retrieve a column from the grids table by giving a proj_uid value.
I'm not very good with SQL joins and I don't know how to build a single query that will achieve that.
Actually, I'm doing 3 queries to perform the operation:
1) This gives me a res_uid to work with:
select res_uid from results where results.proj_uid = VALUE order by res_uid asc limit 1"
2) This gives me a rec_uid to work with:
select rec_uid from receptor_results
inner join results on results.res_uid = receptor_results.res_uid
where receptor_results.res_uid = res_uid_VALUE order by rec_uid asc limit 1
3) Get the grid column I want from the grids table:
select grid_name from grids
inner join receptors on receptors.grid_uid = grids.grid_uid
where receptors.rec_uid = rec_uid_VALUE;
Is it possible to perform a single SQL that will give me the same results the 3 I'm actually doing ?
You're not limited to one JOIN in a query:
select grids.grid_name
from grids
inner join receptors
on receptors.grid_uid = grids.grid_uid
inner join receptor_results
on receptor_results.rec_uid = receptors.rec_uid
inner join results
on results.res_uid = receptor_results.res_uid
where results.proj_uid = VALUE;
select g.grid_name
from results r
join resceptor_results rr on r.res_uid = rr.res_uid
join receptors rec on rec.rec_uid = rr.rec_uid
join grids g on g.grid_uid = rec.grid_uid
where r.proj_uid = VALUE
a small note about names, typically in sql the table is named for a single item not the group. thus "result" not "results" and "receptor" not "receptors" etc. As you work with sql this will make sense and names like you have will seem strange. Also, one less character to type!

MS Access SQL Update with Minimum

This SQL is beyond my expertise. I think it should be fairly easy for someone with experience. Here is what I have so far..
SQL is as follows:
UPDATE (Tbl_Stg_Project_Schedule_Dates
INNER JOIN Tbl_Child_ITN ON Tbl_Stg_Project_Schedule_Dates.ms_itn = Tbl_Child_ITN.ITN)
INNER JOIN Tbl_Schedule ON Tbl_Child_ITN.Id = Tbl_Schedule.ID SET Tbl_Schedule.a_construction_start = [Tbl_Stg_Project_Schedule_Dates].[ms_start_date]
WHERE (((Tbl_Stg_Project_Schedule_Dates.ms_tempt_id) In (16,17,18,19,20,21,22,23)));
I want to add one last condition to this being that I only want the minimum of [Tbl_Stg_Project_Schedule_Dates].[ms_start_date] to update the table. I've tried the obvious of wrapping the field in Min, and also tried creating a separate aggregate select statement first (to get the min value with other criteria) that I then tried to create the update query from in new query but no luck.
I believe this is valid Access/Jet SQL. The idea here is to use a subquery to look up the earliest date among all the rows in your subset. I'm not sure if ms_itn was the right column to correlate on but hopefully you get the idea:
UPDATE (Tbl_Stg_Project_Schedule_Dates
INNER JOIN Tbl_Child_ITN ON Tbl_Stg_Project_Schedule_Dates.ms_itn = Tbl_Child_ITN.ITN)
INNER JOIN Tbl_Schedule ON Tbl_Child_ITN.Id = Tbl_Schedule.ID
SET Tbl_Schedule.a_construction_start = [Tbl_Stg_Project_Schedule_Dates].[ms_start_date]
WHERE (((Tbl_Stg_Project_Schedule_Dates.ms_tempt_id) In (16,17,18,19,20,21,22,23)))
and [Tbl_Stg_Project_Schedule_Dates].[ms_start_date] = (
select min(sd.[ms_start_date])
from [Tbl_Stg_Project_Schedule_Dates] as sd
where sd.ms_itn = [Tbl_Stg_Project_Schedule_Dates].ms_itn
)

SumIF Access - Multiple tables

I am following the question I asked here: SumIF in SQL Access
I have 3 tables [Broker] , [OPT], [TRS]. [Broker] have 2 fields BRKR_CODE, Status and [OPT] and [TRS] Have 5 same fields BRKR1, BRKR2, Date, COM_BRK1, COM_BRKR2
OPT.BRKR1, OPT.BRKR2, TRS.BRKR1, TRS.BRKR2 are linked to Broker.BRKR_CODE and can be equal.
I want to write this query.... If Broker.Status="Active" then Select Broker.BRKR_CODE
and then for each Broker.BRKR_CODE (for example "CB") do the Sum of OPT.COM_BRKR1 when OPT.BRKR1="CB" + Sum of OPT.COM_BRKR2 when OPT.BRKR2="CB" and do the Sum of TRS.COM_BRKR1 when TRS.BRKR1="CB" + Sum of TRS.COM_BRKR2 when TRS.BRKR2="CB"
I wrote this code using the answer I got in the previous question... but still have syntax issue... basically I want to have an array with 3 column BRKR_CODE, OPT_Tot, TRS_Tot
SELECT Broker.BRKR_CODE,
Sum(OPT.COM_BRKR1)+ Sum(OPT.COM_BRKR2) AS OPT_Tot,
Sum(TRS.COM_BRKR1)+ Sum(TRS.COM_BRKR2) AS TRS_Tot
FROM Broker
INNER JOIN OPT
ON (Broker.BRKR_CODE = OPT.BRKR2) OR (Broker.BRKR_CODE = OPT.BRKR1)
INNER JOIN TRS
ON (Broker.BRKR_CODE = TRS.BRKR2) OR (Broker.BRKR_CODE = TRS.BRKR1)
WHERE Broker.Status = "Active"
GROUP BY Broker.BRKR_CODE
You should try to make this query in the designer (just to get the base joins right). You'll see Access does some different stuff with parentheses that other SQL engines don't do.
You need to wrap each set of joins in parentheses
SELECT Broker.BRKR_CODE,
Sum(OPT.COM_BRKR1)+ Sum(OPT.COM_BRKR2) AS OPT_Tot,
Sum(TRS.COM_BRKR1)+ Sum(TRS.COM_BRKR2) AS TRS_Tot
FROM (Broker
INNER JOIN OPT
ON (Broker.BRKR_CODE = OPT.BRKR2) OR (Broker.BRKR_CODE = OPT.BRKR1))
INNER JOIN TRS
ON (Broker.BRKR_CODE = TRS.BRKR2) OR (Broker.BRKR_CODE = TRS.BRKR1)
WHERE Broker.Status = "Active"
GROUP BY Broker.BRKR_CODE

SQL statement structuring

I have two tables AgentFare and SalesHeader having hdrGuid and hdrGuid , DocumentNumber as columns respectively.
I have to perform a query based on Document number, however I am not able to figure out which of the two following queries are most suitable.
SELECT agf.Fare , agf.Tax . agf.Commission
FROM AgentFare as agf
INNER JOIN SalesHeader as h ON agf.hdrGuid = h.hdrGuid AND h.DocumentNumber = 'XYZ'
OR
SELECT agf.Fare , agf.Tax . agf.Commission
FROM AgentFare as agf
INNER JOIN SalesHeader as h ON agf.hdrGuid = h.hdrGuid
WHERE h.DocumentNumber = 'XYZ'
Which of the 2 are more appropriate ?
First method is more appropriate.Since it will take less time as compared to second query.
The "ON" statement should be used to define on what columns 2 tables should be joined.
The "WHERE" statement is intended to filter your results.
The second option is the more appropriate to use.
You might find that this is a case of personal preference. My preference is for the second one. It's clear to me what you are joining on and what you are filtering with. If you change your code so that you replace 'XYZ' with a parameter, then for me the second way is much easier. I expect to find the 'filters' at the bottom.