SQL select statement that checks two columns and returns the value from a third [duplicate] - sql

This question already has answers here:
SQL Server Error:"SQL Server Subquery returned more than 1 value"
(2 answers)
Closed 7 years ago.
I am writing a query that accesses multiple tables in the same database. For one of the columns in the select statement, I need to return
Table1.Column4
where Table1.Column = Table3.Column1 AND
Table1.Column2 = Table4.Column1
I have it written as:
SELECT AccNum.FieldValue
FROM PersonFieldValuesVW
INNER JOIN PersonFieldValuesVW AccNum
ON AccNum.PersonId = InPerson.PersonId
INNER JOIN InPerson
ON InPerson.IncidentId = Incident.Id
WHERE AccNum.FieldDescr like '%Account Number%') as [Account Number],
This is returning the error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Here is the full query, any assistance would be appreciated.
SELECT DISTINCT
CaseNum as [Case Number],
ALCategoryVW.Category as [Category],
ALCategoryVW.SubCategory as [Sub Category],
InAssign.AssignToName as [Assigned To],
ReportedDate as [Open Date],
EndDate as [Closed Date], --This a placeholder for a closed date
[Status],
SiteLoc1.Descr as [Loss Location],
LocDetails as [Loss Cost Center],
SiteLoc1.Region as [Region],
SiteLoc1.SubRegion as [Sub Region],
-- SiteLoc2.Descr as [Location Description], **Need this though returning all for the location?
CASE WHEN SAR.FieldId = '604NU' and SAR.FieldValue <> 'False' THEN 'YES' ELSE 'NO' END as [SAR Required],
Summary as [Incident Summary],
Disposition as [Case Disposition],
(
SELECT AccNum.FieldValue
FROM PersonFieldValuesVW
INNER JOIN PersonFieldValuesVW AccNum ON AccNum.PersonId = InPerson.PersonId
INNER JOIN InPerson ON InPerson.IncidentId = Incident.Id
WHERE AccNum.FieldDescr like '%Account Number%'
) as [Account Number],
FORMAT(AuditItemDetail.ItemValue, '#,###') as [Potential Loss],
FORMAT(AuditItemDetail.ItemValue - AuditItemDetail.PreventedExposureAmount, '#,###') as [Actual Loss]
FROM Incident
INNER JOIN ALCategoryVW ON ALCategoryVW.IncidentId = Incident.Id
INNER JOIN InAssign ON InAssign.IncidentId = Incident.Id
INNER JOIN SiteLoc1 ON SiteLoc1.Id = Incident.LocId
INNER JOIN SiteLoc2 ON SiteLoc2.SiteLoc1Id = SiteLoc1.Id
INNER JOIN IncidentFieldValuesVW SAR ON SAR.IncidentId = Incident.Id
INNER JOIN InItem ON InItem.IncidentId = Incident.Id
INNER JOIN AuditItemDetail ON AuditItemDetail.ItemId = InItem.ItemId
INNER JOIN InPerson ON InPerson.IncidentId = Incident.Id
INNER JOIN PersonFieldValuesVW AccNum ON AccNum.PersonId = InPerson.PersonId

This should resolve your error, but I'm not sure it is logically correct. If you have two records being returned in the sub-select, which one is the "right" one.
SELECT DISTINCT
CaseNum as [Case Number],
ALCategoryVW.Category as [Category],
ALCategoryVW.SubCategory as [Sub Category],
InAssign.AssignToName as [Assigned To],
ReportedDate as [Open Date],
EndDate as [Closed Date], --This a placeholder for a closed date
[Status],
SiteLoc1.Descr as [Loss Location],
LocDetails as [Loss Cost Center],
SiteLoc1.Region as [Region],
SiteLoc1.SubRegion as [Sub Region],
-- SiteLoc2.Descr as [Location Description], **Need this though returning all for the location?
CASE WHEN SAR.FieldId = '604NU' and SAR.FieldValue <> 'False' THEN 'YES' ELSE 'NO' END as [SAR Required],
Summary as [Incident Summary],
Disposition as [Case Disposition],
AccNum.FieldValue,
FORMAT(AuditItemDetail.ItemValue, '#,###') as [Potential Loss],
FORMAT(AuditItemDetail.ItemValue - AuditItemDetail.PreventedExposureAmount, '#,###') as [Actual Loss]
FROM Incident
INNER JOIN ALCategoryVW ON ALCategoryVW.IncidentId = Incident.Id
INNER JOIN InAssign ON InAssign.IncidentId = Incident.Id
INNER JOIN SiteLoc1 ON SiteLoc1.Id = Incident.LocId
INNER JOIN SiteLoc2 ON SiteLoc2.SiteLoc1Id = SiteLoc1.Id
INNER JOIN IncidentFieldValuesVW SAR ON SAR.IncidentId = Incident.Id
INNER JOIN InItem ON InItem.IncidentId = Incident.Id
INNER JOIN AuditItemDetail ON AuditItemDetail.ItemId = InItem.ItemId
INNER JOIN InPerson ON InPerson.IncidentId = Incident.Id
LEFT JOIN PersonFieldValuesVW AccNum ON AccNum.PersonId = InPerson.PersonId AND AccNum.FieldDescr like '%Account Number%'
***Updated based on comment.

Related

How to exclude duplicate values / NULL values SQL

I hope that someone from you will be able to help me as I got stuck with a (silly) condition logic.
I am joining 2 temp tables.
The target is to see the Jobs, Tracking numbers, etc. (all actions) in one row always for one Consignee (Consignee Ref). In other words, to show all actions/data per Consignee Ref.
The issue I got is duplacated values. The problem is that the Original Job (620X) field can have assigned Tracking_1 but it can be also null. Also the Second Job (629X) filed can have but do not need to have assigned the Tracking number/value. It can be also the case that both Tracking_1 and Tracking are NULL for one Consignee Ref.
When I would exclude Jobs where Tracking_1 or Tracking is NULL, then I will loose the Jobs that have no Tracking Numbers at all. So I used the code below, but then I am getting duplicates.
SELECT * FROM #Temp t1
INNER JOIN #Temp2 t2 on t1.[Consignee Ref] = t2.[Consignee Ref]
WHERE t1.[Tracking_1] is not null
ORDER BY [Original Job (620X)] asc
How can I make it that I will get rid of the unnecessary duplicates (an example marked in red)?
And at the same time not to loose those jobs that have no Tracking Numbers?
I hope it makes sense.
Thank you very much in advance for any advise!
This is the entire code:
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
DROP TABLE #Temp;
SELECT distinct
cne.[Consignee Ref],
s.[Trial AWB] as [Original Job (620X)],
rl.[CarrierReference] as [Tracking_1],
CAST(st.[Sched Collection date] as date) AS [Collection Date],
CAST(st.[Act Del Date] as date) AS [Delivery Date],
s.[Clientaccountcode] as [Account Code]
into #Temp
FROM MKN_Reporting.dbo.shipment AS s WITH (NOLOCK)
LEFT JOIN MKN_Reporting.dbo.[Lookup Month By JN Tb] AS b WITH (NOLOCK) ON s.[id] = b.[JobId]
LEFT JOIN MKN_Reporting.dbo.[Lookup Branch currency Tb] AS c WITH (NOLOCK) ON b.BranchPrefix = c.[Branch Prefix]
LEFT JOIN MKN_Reporting.dbo.[Lookup Client group Tb] AS g WITH (NOLOCK) ON s.[Clientaccountcode] = g.[Customer A/c]
LEFT JOIN MKN_Reporting.dbo.[Chargeto] AS cg WITH (NOLOCK) ON s.[id] = cg.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Shipper] AS sh WITH (NOLOCK) ON s.[id] = sh.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Cnee] AS cne WITH (NOLOCK) ON s.[id] = cne.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Lookup Country & Region Tb] AS r WITH (NOLOCK) ON sh.[Shipper Country code] = r.[Country Code]
LEFT JOIN MKN_Reporting.dbo.[Lookup Country & Region Tb] AS reg WITH (NOLOCK) ON cne.[Consignee Country code] = reg.[Country Code]
INNER JOIN MKN_Reporting.dbo.[Status] st ON COALESCE(s.ParentId, s.id) = st.Jobid
LEFT JOIN [CARRIERS_CHARGES] AS cc ON s.id = cc.JobId
LEFT JOIN [RouteLegs] as rl on cc.RouteLegId = rl.id
WHERE [Clientaccountcode] in ('US429', 'MI1091')
--AND rl.[CarrierReference] is not null
-------------------------------------------
IF OBJECT_ID('tempdb..#Temp2') IS NOT NULL
DROP TABLE #Temp2;
SELECT distinct
cne.[Consignee Ref],
s.[Study Number] as [Study_],
s.[Site Number] as [Site No_],
s.[Trial AWB] as [Second (629X)],
rl.[CarrierReference] as [Tracking],
CAST(st.[Sched Collection date] as date) AS [Collection Date],
CAST(st.[Act Del Date] as date) AS [Delivery Date],
s.[Clientaccountcode] as [Account Code]
into #Temp2
FROM MKN_Reporting.dbo.shipment AS s WITH (NOLOCK)
LEFT JOIN MKN_Reporting.dbo.[Lookup Month By JN Tb] AS b WITH (NOLOCK) ON s.[id] = b.[JobId]
LEFT JOIN MKN_Reporting.dbo.[Lookup Branch currency Tb] AS c WITH (NOLOCK) ON b.BranchPrefix = c.[Branch Prefix]
LEFT JOIN MKN_Reporting.dbo.[Lookup Client group Tb] AS g WITH (NOLOCK) ON s.[Clientaccountcode] = g.[Customer A/c]
LEFT JOIN MKN_Reporting.dbo.[Chargeto] AS cg WITH (NOLOCK) ON s.[id] = cg.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Shipper] AS sh WITH (NOLOCK) ON s.[id] = sh.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Cnee] AS cne WITH (NOLOCK) ON s.[id] = cne.[jobid]
LEFT JOIN MKN_Reporting.dbo.[Lookup Country & Region Tb] AS r WITH (NOLOCK) ON sh.[Shipper Country code] = r.[Country Code]
LEFT JOIN MKN_Reporting.dbo.[Lookup Country & Region Tb] AS reg WITH (NOLOCK) ON cne.[Consignee Country code] = reg.[Country Code]
INNER JOIN MKN_Reporting.dbo.[Status] st ON COALESCE(s.ParentId, s.id) = st.Jobid
LEFT JOIN [CARRIERS_CHARGES] AS cc ON s.id = cc.JobId
left JOIN [RouteLegs] as rl on cc.RouteLegId = rl.id
WHERE [Clientaccountcode] in ('US1598')
--AND rl.[CarrierReference] is not null
---------------------------------------------
SELECT * FROM #Temp t1
INNER JOIN #Temp2 t2 on t1.[Consignee Ref] = t2.[Consignee Ref]
WHERE t1.[Tracking_1] is not null
ORDER BY [Original Job (620X)] asc
I guess OP is looking for some kind of field aggregation for T2.
With SQL Server 2017+, like in PostgreSQL, you can now use STRING_AGG (same syntax than the Oracle LISTAGG.. "Why did they not use the same keyword...").
STRING_AGG will ignore null values from T2 and requires grouping if not alone. You have to add the other T1 and T2 required fields if any, but take care for T2 that it can imply duplicates and may need aggregation too...
Here is an example with your provided TSQL :
SELECT t1.[Consignee Ref], t1.[Original Job (620X)], t1.[Tracking_1],
STRING_AGG(t2.[Tracking],',') WITHIN GROUP (ORDER BY t2.[Tracking] ASC) Tracking_T2
FROM #Temp t1
INNER JOIN #Temp2 t2 on t1.[Consignee Ref] = t2.[Consignee Ref]
WHERE t1.[Tracking_1] is not null
GROUP BY t1.[Consignee Ref], t1.[Original Job (620X)], t1.[Tracking_1]
ORDER BY t1.[Original Job (620X)] asc
EDIT: For previous SQL Server release (before 2017), you can achieve string aggregation with XML query :
EDIT2: Adding EXISTS clause to convey the INNER JOIN from the initial query.
SELECT t1.[Consignee Ref], t1.[Original Job (620X)], t1.[Tracking_1],
STUFF((SELECT ', ' + t2.[Tracking]
FROM #Temp2 t2
WHERE t1.[Consignee Ref] = t2.[Consignee Ref]
ORDER BY t2.[Tracking]
FOR XML PATH('')), 1, 1, N'') Tracking_T2
FROM #Temp t1
WHERE t1.[Tracking_1] is not null
AND EXISTS (SELECT DISTINCT 1 FROM #Temp2 t2 WHERE t2.[Consignee Ref] = t1.[Consignee Ref])
GROUP BY t1.[Consignee Ref], t1.[Original Job (620X)], t1.[Tracking_1]
ORDER BY t1.[Original Job (620X)] asc

Query to get the min date for the duplicate records

Below is my query, if there duplicate records I need to filter based on dates.
select
X.[po number],
(X.[ grn number]),
(X.[grn docentry]),
(X.ItemCode),
(X.[grn total]),
(X.tax),
(x.DocDate)[docdate]
from (
SELECT Distinct
T0.[DocNum] [po number],
T3.[DocNum] [ grn number],
T3.DocEntry [grn docentry],
T1.ItemCOde,
(T3.DocDate),
CASE WHEN T3.DocCur != 'SGD'
then (T4.PriceBefDi * T4.Quantity)
ELSE T4.LineTotal
END [grn total],
CASE WHEN T3.DocCur != 'SGD'
THEN T4.VatSumFrgn
ELSE T4.VatSum
END as [tax]
FROM OPOR T0
INNER JOIN POR1 T1 ON T0.DocEntry = T1.DocEntry
INNER JOIN PDN1 T4 on T1.DocEntry = T4.BaseEntry and T1.LineNum = T4.BaseLine
INNER JOIN OPDN T3 on T3.DocEntry = T4.DocEntry
)X
where X.[po number] in (37199, 37431, 37163, 37163, 37548)
and X.[grn total] in (1350.0000, 650.0000, 140.0000, 372.0000, 685.0000)
Below is my result set. if there are similar item codes, amount, tax amount. I need get only one record based on the minimum date for those matching. The highlighted red color must not show in the result set.
The actual output is like below:
You need to aggregate and select - what looks like - the min of each group:
select X.[po number], Min(X.[grn number])[grn number], Min(X.[grn docentry])[grn docentry], X.ItemCode, X.[grn total], X.tax, Min(X.DocDate) [docdate] from (
select distinct T0.[DocNum] [po number], T3.[DocNum] [ grn number], T3.DocEntry [grn docentry], T1.ItemCOde, T3.DocDate,
case when T3.DocCur != 'SGD' then (T4.PriceBefDi * T4.Quantity) else T4.LineTotal end [grn total] ,
case when T3.DocCur != 'SGD' then T4.VatSumFrgn else T4.VatSum end as [tax]
from OPOR T0
inner join POR1 T1 on T0.DocEntry = T1.DocEntry
inner join PDN1 T4 on T1.DocEntry = T4.BaseEntry and T1.LineNum = T4.BaseLine
inner join OPDN T3 on T3.DocEntry = T4.DocEntry
)X
where X.[po number] in (37199, 37431, 37163, 37163, 37548) and X.[grn total] in (1350.0000, 650.0000, 140.0000, 372.0000, 685.0000)
group by X.[po number], X.ItemCode, X.[grn total], X.tax
Use GROUP BY for and set HAVING clause MIN(x.DocDate).
I guess that your unique column is x.ItemCode and add the rest of column.
Sample:
GROUP BY x.ItemCode
HAVING MIN(x.DocDate)
One way is
select top(1) with ties *
from (
-- your original query
) t
order by row_number() over(partition by ItemCode, [grn total], tax order by docdate)

using sql subtotals

I have the following select statement:
SELECT
c.compname AS [Company]
,x.Ressnavn AS [Client]
,a.jobid AS [Job Number]
,a.JobNavn AS [Job Name]
,t.TName [Task Name]
,cu.DayDate AS [Booking Date]
,cu.HrsBooked AS [Scheduled Hours]
,tr.Sale AS [Sales Value]
,(cu.HrsBooked) * (tr.Sale) AS [Total]
FROM job a
INNER JOIN jobplan jp on jp.JobId=a.jobid
INNER JOIN JobDimensions AS z ON z.jobid = a.jobid
INNER JOIN Ress AS x ON x.RessId = z.custid
INNER JOIN JobPrice AS y ON y.JobId = a.Jobid
INNER JOIN task t on t.PlanId = jp.PlanId
INNER JOIN JobPriceactivity AS w ON w.priceId = y.priceId
INNER JOIN taskres tr ON tr.TaskId = t.TaskId
INNER JOIN emp e ON e.EmpId = tr.ResId
INNER JOIN comp c ON e.compid = c.compid
INNER JOIN CapUsed AS cu ON cu.RefId = tr.TaskResId AND cu.RefType=1
INNER JOIN arpaccount AS ar ON e.empname = ar.arpaccname
AND CAST (cu.DayDate AS DATE) BETWEEN #startdate AND #enddate
WHERE c.compid = '107' AND e.EMPID >='2' AND cu.HrsBooked > '0'
GROUP BY
x.Ressnavn
,a.jobid
,a.JobNavn
,t.TName
,cu.DayDate
,cu.HrsBooked
,y.priceid
,tr.Sale
,c.compname
That gives me the following output but I would like to add in a subtotal of the column 'Total' at each change in client.
An example of what I would like to try and get to is highlighted in green on the output screen grab.
Can anyone advise on the best way to do this?
Try using GROUP BY ROLLUP:
SELECT
x.Ressnavn AS [Client],
c.compname AS [Company],
a.jobid AS [Job Number],
a.JobNavn AS [Job Name],
t.TName [Task Name],
cu.DayDate AS [Booking Date],
cu.HrsBooked AS [Scheduled Hours],
tr.Sale AS [Sales Value],
(cu.HrsBooked) * (tr.Sale) AS [Total]
FROM (...)
GROUP BY
x.Ressnavn,
ROLLUP (
c.compname,
a.jobid,
a.JobNavn,
t.TName,
cu.DayDate,
cu.HrsBooked,
y.priceid,
tr.Sale )

SQL: How do I show all Items in Inventory and Sum sales of items sold in a time period?

I am trying to find all items on hand from #Supplier_ID and summarize any sales since #Begin_Date. What is returned are all items on hand that have never been sold and those sold since #Begin_Date. Items on hand that were sold before #Begin_Date are excluded from the results. How do I fix that?
I am using SQL Server 2012 and SSRS v3.
SELECT DISTINCT
inventory_supplier.supplier_id AS [Supp ID],
address.name AS Supplier,
inv_loc.location_id AS [Inventory Loc ID],
inv_mast.item_id AS [Item ID],
inv_mast.item_desc AS [Item Desc],
inv_loc.qty_on_hand AS QOH,
inv_loc.moving_average_cost AS MAC,
invoice_line.qty_shipped,
invoice_hdr.customer_id AS [Customer ID],
invoice_hdr.bill2_name AS Customer,
oe_line.source_loc_id AS [Sales Source Loc]
FROM
inventory_supplier
INNER JOIN
inv_mast ON inventory_supplier.inv_mast_uid = inv_mast.inv_mast_uid
INNER JOIN
address ON inventory_supplier.supplier_id = address.id
FULL OUTER JOIN
invoice_line ON inv_mast.inv_mast_uid = invoice_line.inv_mast_uid
FULL OUTER JOIN
inv_loc ON inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
FULL OUTER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
FULL OUTER JOIN
oe_line ON invoice_hdr.order_no = oe_line.order_no
AND invoice_line.inv_mast_uid = oe_line.inv_mast_uid
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date
OR invoice_hdr.invoice_date IS NULL)
AND (inv_loc.qty_on_hand > 0)
ORDER BY
[Item ID], [Inventory Loc ID], [Customer ID], [Sales Source Loc]
You could move your invoice_hdr.invoice_date >= #Begin_Date to your join statement
FULL OUTER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
AND invoice_hdr.invoice_date >= #Begin_Date
Don't see a lot of FULL OUTER JOINs. Sure you don't want LEFT JOIN here?
You might want to separate out the Invoice information from the Inventory information into a subquery, and LEFT JOIN to the Invoice information.
SELECT DISTINCT
inventory_supplier.supplier_id AS [Supp ID],
address.name AS Supplier,
inv_loc.location_id AS [Inventory Loc ID],
inv_mast.item_id AS [Item ID],
inv_mast.item_desc AS [Item Desc],
inv_loc.qty_on_hand AS QOH,
inv_loc.moving_average_cost AS MAC,
invoices.qty_shipped,
invoices.customer_id AS [Customer ID],
invoices.bill2_name AS Customer,
invoices.source_loc_id AS [Sales Source Loc]
FROM
inventory_supplier
INNER JOIN
inv_mast ON inventory_supplier.inv_mast_uid = inv_mast.inv_mast_uid
INNER JOIN
address ON inventory_supplier.supplier_id = address.id
INNER JOIN
inv_loc ON inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
LEFT OUTER JOIN
(SELECT
invoice_line.inv_mast_uid,
invoice_line.qty_shipped,
invoice_hdr.customer_id,
invoice_hdr.bill2_name,
oe_line.source_loc_id
FROM
invoice_line
INNER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
INNER JOIN
oe_line ON invoice_hdr.order_no = oe_line.order_no
AND invoice_line.inv_mast_uid = oe_line.inv_mast_uid
WHERE
invoice_hdr.invoice_date >= #Begin_Date
) invoices ON invoices.inv_mast_uid = inv_mast.inv_mast_uid
WHERE
inventory_supplier.supplier_id = #Supplier_ID
AND inv_loc.qty_on_hand > 0
ORDER BY
[Item ID], [Inventory Loc ID], [Customer ID], [Sales Source Loc]
Try changing
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date
OR invoice_hdr.invoice_date IS NULL)
AND (inv_loc.qty_on_hand > 0)
to
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date)
AND (inv_loc.qty_on_hand > 0)
The problem is because you are including dates, invoice_hdr.invoice_date that are NULL in the WHERE clause. Simply remove it:
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date)
AND (inv_loc.qty_on_hand > 0)

Consolidating Queries

I'm trying to understand how to combine queries when one of them returns more than one record.
This is an invoicing report where I want to pull in the Serial Numbers of products invoiced. I'll abbreviate the script as much as possible to clarify. Here is my script before adding the serials:
SELECT ARM.fcustno AS [Cust No]
, ARM.fbcompany AS [Cust Name]
, ARM.fcinvoice AS [Invoice No]
, ARM.fdgldate AS [Post Date]
, ARI.fitem AS [Item No]
, ARI.fprodcl AS [Prod Class]
, ARI.fshipkey AS [Qty Invoiced]
, ARI.fpartno AS [Part No]
, ARI.frev AS [Part Rev]
, ARI.FTOTPRICE AS [Net Invoiced]
, ARM.fsono AS [Sales No]
, SOM.fcusrchr2
FROM dbo.armast ARM
INNER JOIN dbo.aritem ARI ON ARM.FCINVOICE = ARI.FCINVOICE
INNER JOIN slcdpm SLC ON SLC.fcustno = ARM.fcustno
LEFT OUTER JOIN slcdpm_ext SLCE ON SLC.identity_column = SLCE.fkey_id
LEFT OUTER JOIN somast SOM ON SOM.fsono = ARM.fsono
This returns invoiced line items, their prices, and such. When I pull in the following:
SELECT ARM.fcustno AS [Cust No]
, ARM.fbcompany AS [Cust Name]
, ARM.fcinvoice AS [Invoice No]
, ARM.fdgldate AS [Post Date]
, ARI.fitem AS [Item No]
, ARI.fprodcl AS [Prod Class]
, ARI.fshipkey AS [Qty Invoiced]
, ARI.fpartno AS [Part No]
, ARI.frev AS [Part Rev]
, ARI.FTOTPRICE AS [Net Invoiced]
, ARM.fsono AS [Sales No]
, SOM.fcusrchr2
, LOTC.fcuseinlot
FROM dbo.armast ARM
INNER JOIN dbo.aritem ARI ON ARM.FCINVOICE = ARI.FCINVOICE
INNER JOIN slcdpm SLC ON SLC.fcustno = ARM.fcustno
LEFT OUTER JOIN slcdpm_ext SLCE ON SLC.identity_column = SLCE.fkey_id
LEFT OUTER JOIN somast SOM ON SOM.fsono = ARM.fsono
--** New stuff below: ******
LEFT OUTER JOIN ShItem SHI ON SHI.fShipNo + SHI.fItemNo = ARI.fShipKey
LEFT OUTER JOIN ShSrce ON ShSrce.fcShipNo = SHI.fShipNo
AND ShSrce.fcItemNo = SHI.fItemNo
LEFT OUTER JOIN QaLotC LOTC ON LOTC.fcUseInDoc = ShSrce.fcShipNo + ShSrce.fcItemNo + ShSrce.fcSrcItmNo
The problem is that there can be multiple SHSRCE records per invoice. What is the best way to handle this? Perhaps use a subquery to concatenate the LOTC.fcuseinlot field in order to return one corresponding value per record.
To clarify, the additional query returns more than 1 record per line item invoice because multiple serial number parts can be invoiced on one line item. Ideally, I'd like them to be concatenated like (NCC1701, R2D2, C3PO) etc. That's why I thought about using a subquery to concatenate them.
Still waiting for the OP to clarify the question, but if the multiple SHSRCE records still only relate to one serialnumber (which i am presuming is in LOTC.fcuseinlot)
SELECT
ARM.fcustno AS [Cust No] ,
ARM.fbcompany AS [Cust Name] ,
ARM.fcinvoice AS [Invoice No] ,
ARM.fdgldate AS [Post Date] ,
ARI.fitem AS [Item No] ,
ARI.fprodcl AS [Prod Class] ,
ARI.fshipkey AS [Qty Invoiced] ,
ARI.fpartno AS [Part No] ,
ARI.frev AS [Part Rev] ,
ARI.FTOTPRICE AS [Net Invoiced] ,
ARM.fsono AS [Sales No] ,
SOM.fcusrchr2,
MAX(LOTC.fcuseinlot)
FROM
dbo.ARMAST ARM
JOIN dbo.aritem ARI ON ARI.FCINVOICE = ARM.FCINVOICE
JOIN slcdpm SLC ON SLC.fcustno = ARM.fcustno
LEFT JOIN slcdpm_ext SLCE ON SLCE.fkey_id = SLC.identity_column
LEFT JOIN somast SOM ON SOM.fsono = ARM.fsono
LEFT JOIN ShItem SHI ON SHI.fShipNo + SHI.fItemNo = ARI.fShipKey
LEFT JOIN ShSrce ON ShSrce.fcShipNo = SHI.fShipNo AND ShSrce.fcItemNo = SHI.fItemNo
LEFT JOIN QaLotC LOTC ON LOTC.fcUseInDoc = ShSrce.fcShipNo + ShSrce.fcItemNo + ShSrce.fcSrcItmNo
GROUP BY
ARM.fcustno ,
ARM.fbcompany ,
ARM.fcinvoice ,
ARM.fdgldate ,
ARI.fitem ,
ARI.fprodcl ,
ARI.fshipkey ,
ARI.fpartno ,
ARI.frev ,
ARI.FTOTPRICE ,
ARM.fsono ,
SOM.fcusrchr2
can you post some sample data.
If I'm getting you right, take a look at this kind of sql
create table tableA (id int, ref varchar(50))
insert into tableA
select 1, 3536757616
union select 1, 3536757617
union select 1, 3536757618
union select 2, 3536757628
union select 2, 3536757629
union select 2, 3536757630
I know I can simply concatenate the refs by using
SELECT distinct
id,
stuff ( ( SELECT
'/ ' + ref
FROM
tableA tableA_1
where tableA_1.id = tableA_2.id
FOR XML PATH ( '' ) ) , 1 , 2 , '' )
from TableA tableA_2
to give
1 3536757616/ 3536757617/ 3536757618
2 3536757628/ 3536757629/ 3536757630
Combine queries? As in do a UNION?
What we really need to know is what basis are you going to use to choose which of the possible records has the values you want returned? That will determine the best possibilites for you.
And as you aren't adding any columns and you are using left joins (so no records will be excluded from the joins) what is it you expect to accomplish by adding these joins except to lengthen processing time?
You've got a SQL Server 2000 tag on your question, so I'm not sure this is going to be possible for you. In SQL Server 2005 and above, you can create custom aggregate functions. I use an aggregate function FormDelimitedString, which does exactly what you are looking for.
There is a page here which describes how to implement this function - it gets written as a .NET assembly and then executed from within your queries. With this in place, your query becomes...
SELECT ARM.fcustno AS [Cust No]
, ARM.fbcompany AS [Cust Name]
-- (a few fields skipped for brevity)
, SOM.fcusrchr2
-- Aggregate function will combine multiple values into a single string - 'value1, value2, value3' etc
, dbo.FormDelimitedString(LOTC.fcuseinlot) AS ConcatenatedValues
FROM dbo.armast ARM
INNER JOIN dbo.aritem ARI ON ARM.FCINVOICE = ARI.FCINVOICE
INNER JOIN slcdpm SLC ON SLC.fcustno = ARM.fcustno
LEFT OUTER JOIN slcdpm_ext SLCE ON SLC.identity_column = SLCE.fkey_id
LEFT OUTER JOIN somast SOM ON SOM.fsono = ARM.fsono
LEFT OUTER JOIN ShItem SHI ON SHI.fShipNo + SHI.fItemNo = ARI.fShipKey
LEFT OUTER JOIN ShSrce ON ShSrce.fcShipNo = SHI.fShipNo
AND ShSrce.fcItemNo = SHI.fItemNo
LEFT OUTER JOIN QaLotC LOTC ON LOTC.fcUseInDoc = ShSrce.fcShipNo + ShSrce.fcItemNo + ShSrce.fcSrcItmNo
-- Group by clause needed as its an aggregate function
GROUP BY ARM.fcustno, ARM.fbcompany, SOM.fcusrchr2