LEFT JOIN in Query returning more records than desired - sql

I'm working on an MS ACCESS query which should pull all available data from one main table (specified by FROM) and then joining three additional tables via LEFT JOIN. My issue is that the query is returning more records because of a one to many relationship.
Is there any way I can return only ONE record per line in the main table? Any help is greatly appreciated!! Thank you!
SELECT tbl_Item_PO.Item,
tbl_ItemSKUType.SKU,
tbl_Item_PO.[EX-FACTORY DATE],
tbl_Item_PO.[QTY PER SHIPMENT],
IIf(tbl_Item_PO.Item=Posted_Inv_Tran.Item And tbl_Item_PO.Whse=Posted_Inv_Tran.Whse And tbl_Item_PO.[ITR#]=Posted_Inv_Tran.[TRN Number],0,tbl_Item_PO.[QTY PER SHIPMENT]) AS QTY,
tbl_Item_PO.WHSE, tbl_WhseRegion.Region
FROM ((tbl_Item_PO
LEFT JOIN tbl_ItemSKUType ON tbl_Item_PO.item = tbl_ItemSKUType.Item)
LEFT JOIN tbl_WhseRegion ON tbl_Item_PO.WHSE = tbl_WhseRegion.Whse)
LEFT JOIN Posted_Inv_Tran ON (tbl_Item_PO.[ITR#] = Posted_Inv_Tran.[TRN Number]) AND (tbl_Item_PO.Whse = Posted_Inv_Tran.Whse) AND (tbl_Item_PO.Item = Posted_Inv_Tran.Item);
I've also tried creating sub-queries within the join statements that return only ONE record but I cannot get that to work either:
SELECT po.Item,
ist.SKU,
po.[EX-FACTORY DATE],
po.[QTY PER SHIPMENT],
IIf(po.Item=itr.Item And po.Whse=itr.Whse And po.[ITR#]=itr.[TRN Number],0,po.[QTY PER SHIPMENT]) AS QTY,
po.WHSE,
wh.Region
FROM ((tbl_Item_PO po
LEFT JOIN (select top 1 * from tbl_ItemSKUType
RIGHT JOIN tbl_Item_PO on tbl_ItemSKUType.Item = tbl_Item_PO.item
WHERE tbl_Item_PO.Item = tbl_ItemSKUType.Item)
ist ON po.item = ist.Item)
LEFT JOIN (select top 1 * from tbl_WhseRegion
RIGHT JOIN tbl_Item_PO on tbl_WhseRegion.Whse = tbl_Item_PO.Whse
WHERE tbl_Item_PO.whse = tbl_WhseRegion.Whse)
wh ON po.Whse = wh.Whse)
LEFT JOIN (select top 1 * from Posted_Inv_Tran
RIGHT JOIN tbl_Item_PO on Posted_Inv_Tran.[TRN Number] = tbl_Item_PO.[ITR#] AND Posted_Inv_Tran.Whse = tbl_Item_PO.Whse AND Posted_Inv_Tran.Item = tbl_Item_PO.Item
WHERE (tbl_Item_PO.[ITR#] = Posted_Inv_Tran.[TRN Number]) AND (tbl_Item_PO.Whse = Posted_Inv_Tran.Whse) AND (tbl_Item_PO.Item = Posted_Inv_Tran.Item))
it ON (po.[ITR#] = it.[TRN Number]) AND (po.Whse = it.Whse) AND (po.Item = it.Item);

You can achieve that with a group by clause. Make sure to list all fields in that clause which identify a line, and that all other expressions/fields you have in the select clause are aggregated with some aggregation function, like Min().
NB: Your IIf condition does not need to check all those fields, just one is enough: when one matches, all will match:
SELECT tbl_Item_PO.Item,
Min(tbl_ItemSKUType.SKU) AS SKU,
tbl_Item_PO.[EX-FACTORY DATE],
tbl_Item_PO.[QTY PER SHIPMENT],
Min(IIf(tbl_Item_PO.Item=Posted_Inv_Tran.Item, 0,
tbl_Item_PO.[QTY PER SHIPMENT])) AS QTY,
tbl_Item_PO.WHSE,
Min(tbl_WhseRegion.Region) AS Region
FROM ((tbl_Item_PO
LEFT JOIN tbl_ItemSKUType
ON tbl_Item_PO.item = tbl_ItemSKUType.Item)
LEFT JOIN tbl_WhseRegion
ON tbl_Item_PO.WHSE = tbl_WhseRegion.Whse)
LEFT JOIN Posted_Inv_Tran
ON (tbl_Item_PO.[ITR#] = Posted_Inv_Tran.[TRN Number])
AND (tbl_Item_PO.Whse = Posted_Inv_Tran.Whse)
AND (tbl_Item_PO.Item = Posted_Inv_Tran.Item)
GROUP BY tbl_Item_PO.Item,
tbl_Item_PO.[EX-FACTORY DATE],
tbl_Item_PO.[QTY PER SHIPMENT],
tbl_Item_PO.WHSE;

Related

How to do multiple Left join with multiple ids with just 1 row (Top 1) on the right table

Im doing Multiple left joins on multiple Ids. Im trying to match only 1 result from the right table but not sure how to write the nested select when the join is on multiple IDs.
The last 2 left joins return more than 1 row even with the joins on multiple IDs (expected) however I'm only interested in matching ONE (Top 1) of the result on the right table.
I've already checked out other posts regarding left joins but none of them includes joining with multiple ids.
Basically I'm trying to get a list of operations from the Operation Table (Left Table) . Each operation has an identifier with the Type, Base ID, Lot ID, Split ID, Sub ID & Sequence No which lead to a unique operation. All the tables mentioned have each of these columns present.
However, the "Requirement" table "R" may have more than 1 row for each unique operation and I only need 1 requirement from it. Same is the case for the "Operation_Audit" table "OA".
I've only put 1 column for each table under the select for ease of reading.
Select
O.SETUP_HRS As [Setup Time], O.RUN_HRS As [Run Time],
OS.RESOURCE_ID As [Shop Resource],
WO.PART_ID As [Part ID / Assy],
P.DESCRIPTION As [Part / Assy Description],
WOV.DESCRIPTION As Description,
R.CLOSE_DATE As [Req Issue Date],
OA.RESULT_DETAIL As Reason
From OPERATION As O
Inner Join OPERATION_SCHED OS On
O.WORKORDER_TYPE = OS.WORKORDER_TYPE And
O.WORKORDER_BASE_ID = OS.WORKORDER_BASE_ID And
O.WORKORDER_LOT_ID = OS.WORKORDER_LOT_ID And
O.WORKORDER_SPLIT_ID = OS.WORKORDER_SPLIT_ID And
O.WORKORDER_SUB_ID = OS.WORKORDER_SUB_ID And
O.SEQUENCE_NO = OS.SEQUENCE_NO
Inner Join WORK_ORDER WO On
O.WORKORDER_TYPE = WO.[TYPE] And
O.WORKORDER_BASE_ID = WO.BASE_ID And
O.WORKORDER_LOT_ID = WO.LOT_ID And
O.WORKORDER_SPLIT_ID = WO.SPLIT_ID
Left Outer Join PART P On
P.ID = WO.PART_ID
Inner Join CR_WO_PART WOV On
O.WORKORDER_TYPE = WOV.[TYPE] And
O.WORKORDER_BASE_ID = WOV.BASE_ID And
O.WORKORDER_LOT_ID = WOV.LOT_ID And
O.WORKORDER_SPLIT_ID = WOV.SPLIT_ID And
O.WORKORDER_SUB_ID = WOV.SUB_ID
Left Outer Join REQUIREMENT R On
O.WORKORDER_TYPE = R.WORKORDER_TYPE And
O.WORKORDER_BASE_ID = R.WORKORDER_BASE_ID And
O.WORKORDER_LOT_ID = R.WORKORDER_LOT_ID And
O.WORKORDER_SPLIT_ID = R.WORKORDER_SPLIT_ID And
O.SEQUENCE_NO = R.OPERATION_SEQ_NO And
O.WORKORDER_SUB_ID = R.WORKORDER_SUB_ID
Left Outer Join OPERATION_AUDIT OA On
O.WORKORDER_TYPE = OA.WORKORDER_TYPE And
O.WORKORDER_BASE_ID = OA.WORKORDER_BASE_ID And
O.WORKORDER_LOT_ID = OA.WORKORDER_LOT_ID And
O.WORKORDER_SPLIT_ID = OA.WORKORDER_SPLIT_ID And
O.WORKORDER_SUB_ID = OA.WORKORDER_SUB_ID And
O.SEQUENCE_NO = OA.SEQUENCE_NO And
OA.RESULT = 'M'
Where
O.COMPLETED_QTY <= O.CALC_END_QTY And
WO.SUB_ID = '0' And
O.WORKORDER_TYPE = 'W' And
OS.SCHEDULE_ID = 'STANDARD' And
FilterCriteria = #FilterCriteria
I would create the queries that result in the desired one row being returned for each unique operation from tables R and OA. Then set those queries up as common table expressions (CTE). Then do your original query above (left is good enough, left outer not needed) but join to the single record CTE's instead of R and OA.

SQL - unable to group data getting error message

Select
lot_loc.whse,
lot_loc.item,
item.Ufprofile,
item.UfColor,
item.Uflength,
item.unit_weight*Lot_loc.qty_on_hand 'QTY LBS. On Hand',
item.unit_weight*Lot_loc.qty_rsvd 'QTY LBS. Reserved',
item.UfQtyPerSkid,
lot_loc.loc,
Lot_loc.lot,
Lot_loc.qty_on_hand,
Lot_loc.qty_rsvd,
itemwhse.qty_reorder,
DateDiff(day, lot.Create_Date, GetDate())'Days Old',
lot_loc.CreateDate,
coitem.co_num,
coitem.co_line,
coitem.co_cust_num,
custaddr.name,
coitem.due_date,
item.description,
item.unit_weight*item.lot_size 'STD Run Size (Lbs.)'
from lot_loc_mst lot_loc
left outer join rsvd_inv_mst rsvd_inv on lot_loc.lot = rsvd_inv.lot
LEFT OUTER JOIN coitem_mst coitem ON coitem.co_num = rsvd_inv.ref_num
AND coitem.co_line = rsvd_inv.ref_line
AND coitem.item = rsvd_inv.item
left join custaddr_mst custaddr on coitem.co_cust_num = custaddr.cust_num and coitem.cust_seq = custaddr.cust_seq
Left join item_mst item on lot_loc.item = item.item
left join itemwhse_mst itemwhse on lot_loc.item = itemwhse.item
and lot_loc.whse = itemwhse.whse
inner join lot_mst lot on Lot_loc.lot = lot.lot
I need to group the data by qty lbs on hand. Not sure how to do it. I get a error message when i try to do it.
Error :Column 'lot_loc_mst.whse' is invalid in the select list because
it is not contained in either an aggregate function or the GROUP BY
clause.
Just an example to try and help you with aggregation. I havent included every column but hopefully you can understand it enough to complete it yourself. If you want to group by a column all other columns must be either included in the group by clause as well or use an aggregate function such as SUM, MIN, MAX depending on what you want from that column. Otherwise SQL doesnt know what to do with these columns
e.g.
SELECT * FROM
(
Select
min(item.Uflength) AS [Item Length],
SUM(item.unit_weight*Lot_loc.qty_on_hand) [QTY LBS. On Hand],
SUM(item.unit_weight*Lot_loc.qty_rsvd) [QTY LBS. Reserved],
min(item.UfQtyPerSkid) AS [Qty Per Skid],
DateDiff(day, min(lot.Create_Date), GetDate())[Days Old],
min(item.description) AS [Item Description],
SUM(item.unit_weight*item.lot_size) [STD Run Size (Lbs.)]
from lot_loc_mst lot_loc
left outer join rsvd_inv_mst rsvd_inv on lot_loc.lot = rsvd_inv.lot
LEFT OUTER JOIN coitem_mst coitem ON coitem.co_num = rsvd_inv.ref_num
AND coitem.co_line = rsvd_inv.ref_line
AND coitem.item = rsvd_inv.item
left join custaddr_mst custaddr on coitem.co_cust_num = custaddr.cust_num and
coitem.cust_seq = custaddr.cust_seq
Left join item_mst item on lot_loc.item = item.item
left join itemwhse_mst itemwhse on lot_loc.item = itemwhse.item
and lot_loc.whse = itemwhse.whse
inner join lot_mst lot on Lot_loc.lot = lot.lot
) P
GROUP BY [QTY LBS. On Hand]
all the columns that are not being aggregated must be in the group by
for example
select a, b, sum(c)
from tab
group by a,b <-- maybe you are missing this part

mssql query sum one field among other fields

I need to achieve something like this:
SELECT AttendDetails.Date,AttendDetails.AttendId, NameCode,PhoneNo,Patients.
[Next of Kin] as NextOfKin,Company,
ConsultFee,LabFee, XraFee as XrayFee, ECGFee,
AdmitFee,SUM(PresFee) AS TotalPresFee,MedFee,TheaterFee,ScanFee
FROM AttendDetails
LEFT JOIN Patients on AttendDetails.OPDNo = Patients.OPDNo
LEFT JOIN [Company list] on [Company list].AcNum = AttendDetails.GLOffset
LEFT JOIN ConsultDetails on AttendDetails.AttendId =
ConsultDetails.AttendId
LEFT JOIN LaboratoryDetails on AttendDetails.AttendId =
LaboratoryDetails.AttendId
LEFT JOIN XrayDetails on AttendDetails.AttendId = XrayDetails.AttendId
LEFT JOIN ECGDetails on AttendDetails.AttendId = ECGDetails.AttendId
LEFT JOIN AdmitDetails on AttendDetails.AttendId = AdmitDetails.AttendId
LEFT JOIN PrescripDetails on AttendDetails.AttendId =
PrescripDetails.AttendId
LEFT JOIN Medicals on AttendDetails.AttendId = Medicals.AttendId
LEFT JOIN TheaterDetails on AttendDetails.AttendId = TheaterDetails.AttendId
LEFT JOIN ScanDetails on AttendDetails.AttendId = ScanDetails.AttendId
WHERE AttendDetails.GLOffset = $P{company}
AND AttendDetails.Date BETWEEN $P{startDate} AND $P{endDate}
GROUP BY <something>
where one of the fields in the result is a SUM value. But i seem to not be getting the group by clause right. Or am I doing it all wrong??
During an aggregate query, all fields need to be either part of the GROUP BY clause or affected by an aggregate function. In this case, since you're only aggregating one column, your group by must be all remaining fields:
GROUP BY
AttendDetails.Date,
AttendDetails.AttendId,
NameCode,
PhoneNo,
Patients.[Next of Kin],
Company,
ConsultFee,
LabFee,
XraFee,
ECGFee,
AdmitFee,
MedFee,
TheaterFee,
ScanFee

Access query to include all records even if one field has missing data (is Null)

I am trying run a query to include all records. it is omitting records if one of the fields is null. Changing the "output all fields" in query properties to Yes brings in all fields but that is not what i need. i need all records. Here is my SQL query:
SELECT tblBOOK.Concat, tblBOOK.Owner1, tblBOOK.Owner2,
tblIndustry.[Industry Name], tblOwner1.Points, tblOwner2.Points,
tblIndustry.[Industry Points], tblBOOK.FILE, tblBOOK.SCORE,
tblFILE.Points, tblSCORE.Points, tblBOOK.Risk, tblRisk.Points,
[tblOwner1]![Points]+[tblOwner2]![Points]+[Industry Points]+
[tblFILE]! [Points]+[tblSCORE]![Points]+[tblRisk]![Points]
AS TtlPoints
FROM tblRisk
INNER JOIN (tblSCORE
INNER JOIN (tblFILE
INNER JOIN ((tblOwner1
INNER JOIN (tblOwner2
INNER JOIN tblBOOK
ON (tblOwner2.Secondary = tblBOOK.Owner2)
AND (tblOwner2.Primary = tblBOOK.Owner1))
ON tblOwner1.Primary = tblOwner2.Primary)
INNER JOIN tblIndustry
ON tblBOOK.Industry = tblIndustry.[Industry Name])
ON tblFILE.Score = tblBOOK.FILE)
ON tblSCORE.Score = tblBOOK.SCORE)
ON tblRisk.Factor = tblBOOK.Risk;
I also tried to add "IsNull" to the criteria and then in returns no records.
I needed to change these from INNER JOINS to LEFT JOINS
SELECT tblBOOK.Concat, tblIndustry.[Industry Name],tblIndustry.[Industry Points],
tblOwner1.Primary, tblOwner1.Points, tblFILE.Score, tblFILE.Points, tblCARD.Score,
tblCARD.Points, tblRisk.Factor, tblRisk.Points,
[Industry Points]+[tblOwner1]![Points]+[tblFILE]![Points]+[tblCARD]![Points]+
[tblRisk]![Points]
AS TotalPoints
FROM ((((tblBOOK
LEFT JOIN tblIndustry ON tblBOOK.Industry = tblIndustry.[Industry Name])
LEFT JOIN tblOwner1 ON tblBOOK.Owner1 = tblOwner1.Primary)
LEFT JOIN tblFILE ON tblBOOK.CSS = tblFILE.Score)
LEFT JOIN tblCARD ON tblBOOK.CARD = tblCARD.Score)
LEFT JOIN tblRisk ON tblBOOK.Risk = tblRisk.Factor;

Cannot get both records with SQL/Bigquery JOINs

I've got a query that returns order details, I want information from the briisk table for deals it has found. I also want it to display orders even if the briisk table has nothing.
If I add the final line (and flostream.briisk.master = "") my query only returns one result instead of two.
SELECT *
FROM (SELECT orderno,ifnull(dealid,sales_rule) as DealIDCombo from flostream.orders left join mobileheads.surveys on mobileheads.surveys.order_number = flostream.orders.externalreference) as first
INNER JOIN flostream.orders on first.orderno = flostream.orders.orderno
LEFT JOIN flostream.briisk on first.dealidcombo = flostream.briisk.uniquereference
WHERE first.orderno in (359692,359683)
//AND flostream.briisk.master = ""
When you use a left outer join, then you need to include filter conditions on the second table in the on clause. So try this:
SELECT *
FROM (SELECT orderno,ifnull(dealid,sales_rule) as DealIDCombo
from flostream.orders left join
mobileheads.surveys
on mobileheads.surveys.order_number = flostream.orders.externalreference
) as first INNER JOIN
flostream.orders
on first.orderno = flostream.orders.orderno LEFT JOIN
flostream.briisk
on first.dealidcombo = flostream.briisk.uniquereference AND
flostream.briisk.master = ""
WHERE first.orderno in (359692, 359683)
Conditions on the first table should go in the WHERE clause.