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

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)

Related

Getting Null Value joining 3 tables

Below is the Query,I had joined 3 tables supplier is main table. The actual scenario is I want all the data from table account payable table though it is not their in purchase order table, so I have joined using FULL Outer with supplier and Purchase Order, but the supplier details were not coming against the data of account payable though supplier key is available.
SELECT ISNULL(dbo.Supplier.supplier_key,dbo.Fact_AccountPayables.supplier_key) AS supplier_key,
dbo.Supplier.Supplier,
dbo.Supplier.Name,
dbo.Supplier.Status,
dbo.Supplier.AddressCode,
dbo.Supplier.Address,
dbo.Supplier.HouseNo,
dbo.Supplier.Street,
dbo.Supplier.City,
dbo.Supplier.Country,
dbo.Supplier.ZipCode,
dbo.Supplier.StartDate,
dbo.Supplier.CreditLimit,
dbo.Supplier.FinancialGroup,
dbo.Supplier.LastTransactionDate,
dbo.Fact_PurchaseOrder.Company,
ISNULL(dbo.Fact_PurchaseOrder.[Purchase Order],dbo.Fact_AccountPayables.[PO Number]) AS PurchaseOrder,
ISNULL( dbo.Fact_PurchaseOrder.Sequence,dbo.Fact_AccountPayables.Line) AS POSequence,
dbo.Fact_PurchaseOrder.[Order Quantity],
dbo.Fact_PurchaseOrder.[Per Purchase Unit],
dbo.Fact_PurchaseOrder.[Per Quantity Price],
dbo.Fact_PurchaseOrder.[Purchase price unit],
dbo.Fact_PurchaseOrder.[Total Order Amount],
dbo.Fact_PurchaseOrder.Currency,
dbo.Fact_PurchaseOrder.[Rate Date],
dbo.Fact_PurchaseOrder.[Actual Receipt Date],
dbo.Fact_PurchaseOrder.[Receipt No],
dbo.Fact_PurchaseOrder.[Receipt Sequence],
dbo.Fact_PurchaseOrder.[Received Quantity],
dbo.Fact_PurchaseOrder.[Approved Quantity],
dbo.Fact_PurchaseOrder.[Purchase Office],
dbo.Fact_PurchaseOrder.[Invoice Number],
dbo.Fact_PurchaseOrder.[Invoice Date],
dbo.Fact_PurchaseOrder.[Invoice Quantity],
dbo.Fact_PurchaseOrder.[Invoice Amount],
dbo.Fact_AccountPayables.InvoiceNumber,
dbo.Fact_AccountPayables.Type AS InvoiceType,
dbo.Fact_AccountPayables.[Order Type] AS OrderInvoiceType,
dbo.Fact_AccountPayables.AP_Balance_EUR,
dbo.Fact_AccountPayables.[Invoice Amount_EUR],
dbo.Fact_AccountPayables.supplier_key AS EXPR2,
dbo.Fact_AccountPayables.[IntercompanyTrade Order No] AS EXPR23,
dbo.Fact_AccountPayables.[IntercompanyTrade Line Number] AS EXPR24,
dbo.Fact_AccountPayables.[Intercompany Trade Financial Company] AS EXPR25,
dbo.Fact_AccountPayables.[Intercompany Trade Purchase Company] AS EXPR26,
dbo.Fact_AccountPayables.InvoiceNumber,
dbo.Fact_AccountPayables.DueDate,
dbo.Fact_AccountPayables.DocDate,
dbo.Fact_PurchaseOrder.[Order Date],
dbo.Fact_AccountPayables.[Invoice Amount_EUR],
(CASE WHEN dbo.Fact_PurchaseOrder.[Receipt No] = ' ' THEN dbo.Fact_PurchaseOrder.[Total Order Amount]
WHEN dbo.Fact_PurchaseOrder.[Receipt No] != ' ' and dbo.Fact_AccountPayables.InvoiceNumber IS NULL then dbo.Fact_PurchaseOrder.[Total Order Amount] END) AS ORDERBALANCE,
(dbo.Supplier.CreditLimit -(ORDERBALANCE + dbo.Fact_AccountPayables.[Invoice Amount_EUR])) AS Availablecredit
FROM dbo.Supplier
LEFT OUTER JOIN dbo.Fact_PurchaseOrder ON dbo.Supplier.supplier_key = dbo.Fact_PurchaseOrder.buyfrom_supplier_key
full OUTER JOIN dbo.Fact_AccountPayables ON dbo.Fact_AccountPayables.supplier_key = dbo.Supplier.supplier_key AND
dbo.Fact_AccountPayables.[PO Number] = dbo.Fact_PurchaseOrder.[Purchase Order] AND
dbo.Fact_AccountPayables.[PO Line] = dbo.Fact_PurchaseOrder.Sequence
The output is like this:
Try your Payable table after that FROM Clause and join the other tables by using LEFT JOIN
FROM dbo.Fact_AccountPayables
LEFT JOIN dbo.Fact_PurchaseOrder ON dbo.Fact_AccountPayables.[PO Number] = dbo.Fact_PurchaseOrder.[Purchase Order] AND
dbo.Fact_AccountPayables.[PO Line] = dbo.Fact_PurchaseOrder.Sequence
LRFT JOIN dbo.Supplier ON dbo.Supplier.supplier_key = dbo.Fact_PurchaseOrder.buyfrom_supplier_key AND dbo.Fact_AccountPayables.supplier_key = dbo.Supplier.supplier_key
You have used not only supplier key, but also PO number and PO line as join criterion with full outer join. If there is no matching entry for these (matching entries for ALL join criteria in the same time) in supplier table you will also see the null values you mentioned.
Just for testing remove temporarily the other join criteria (PO number and line) and leave only the supplier key. Check if you still see the null values in this case.
You're using a FULL join for the Fact_AccountPayables table. This way, all records from Fact_AccountPayables are included even if there are no matches with the other two tables. If you don't want that, use LEFT join instead of FULL join.
SELECT
ISNULL(dbo.Supplier.supplier_key, dbo.Fact_AccountPayables.supplier_key) AS supplier_key,
dbo.Supplier.Supplier,
dbo.Supplier.Name,
dbo.Supplier.Status,
dbo.Supplier.AddressCode,
dbo.Supplier.Address,
dbo.Supplier.HouseNo,
dbo.Supplier.Street,
dbo.Supplier.City,
dbo.Supplier.Country,
dbo.Supplier.ZipCode,
dbo.Supplier.StartDate,
dbo.Supplier.CreditLimit,
dbo.Supplier.FinancialGroup,
dbo.Supplier.LastTransactionDate,
dbo.Fact_PurchaseOrder.Company,
ISNULL(dbo.Fact_PurchaseOrder.[Purchase Order], dbo.Fact_AccountPayables.[PO Number]) AS PurchaseOrder,
ISNULL(dbo.Fact_PurchaseOrder.Sequence, dbo.Fact_AccountPayables.Line) AS POSequence,
dbo.Fact_PurchaseOrder.[Order Quantity],
dbo.Fact_PurchaseOrder.[Per Purchase Unit],
dbo.Fact_PurchaseOrder.[Per Quantity Price],
dbo.Fact_PurchaseOrder.[Purchase price unit],
dbo.Fact_PurchaseOrder.[Total Order Amount],
dbo.Fact_PurchaseOrder.Currency,
dbo.Fact_PurchaseOrder.[Rate Date],
dbo.Fact_PurchaseOrder.[Actual Receipt Date],
dbo.Fact_PurchaseOrder.[Receipt No],
dbo.Fact_PurchaseOrder.[Receipt Sequence],
dbo.Fact_PurchaseOrder.[Received Quantity],
dbo.Fact_PurchaseOrder.[Approved Quantity],
dbo.Fact_PurchaseOrder.[Purchase Office],
dbo.Fact_PurchaseOrder.[Invoice Number],
dbo.Fact_PurchaseOrder.[Invoice Date],
dbo.Fact_PurchaseOrder.[Invoice Quantity],
dbo.Fact_PurchaseOrder.[Invoice Amount],
dbo.Fact_AccountPayables.InvoiceNumber,
dbo.Fact_AccountPayables.Type AS InvoiceType,
dbo.Fact_AccountPayables.[Order Type] AS OrderInvoiceType,
dbo.Fact_AccountPayables.AP_Balance_EUR,
dbo.Fact_AccountPayables.[Invoice Amount_EUR],
dbo.Fact_AccountPayables.supplier_key AS EXPR2,
dbo.Fact_AccountPayables.[IntercompanyTrade Order No] AS EXPR23,
dbo.Fact_AccountPayables.[IntercompanyTrade Line Number] AS EXPR24,
dbo.Fact_AccountPayables.[Intercompany Trade Financial Company] AS EXPR25,
dbo.Fact_AccountPayables.[Intercompany Trade Purchase Company] AS EXPR26,
dbo.Fact_AccountPayables.InvoiceNumber,
dbo.Fact_AccountPayables.DueDate,
dbo.Fact_AccountPayables.DocDate,
dbo.Fact_PurchaseOrder.[Order Date],
dbo.Fact_AccountPayables.[Invoice Amount_EUR],
CASE
WHEN dbo.Fact_PurchaseOrder.[Receipt No] = ' ' THEN dbo.Fact_PurchaseOrder.[Total Order Amount]
WHEN dbo.Fact_AccountPayables.InvoiceNumber IS NULL THEN dbo.Fact_PurchaseOrder.[Total Order Amount]
END AS ORDERBALANCE,
dbo.Supplier.CreditLimit - (ORDERBALANCE + dbo.Fact_AccountPayables.[Invoice Amount_EUR]) AS Availablecredit
FROM
dbo.Supplier
LEFT JOIN dbo.Fact_PurchaseOrder ON dbo.Supplier.supplier_key = dbo.Fact_PurchaseOrder.buyfrom_supplier_key
LEFT JOIN dbo.Fact_AccountPayables ON
dbo.Fact_AccountPayables.supplier_key = dbo.Supplier.supplier_key AND
dbo.Fact_AccountPayables.[PO Number] = dbo.Fact_PurchaseOrder.[Purchase Order] AND
dbo.Fact_AccountPayables.[PO Line] = dbo.Fact_PurchaseOrder.Sequence
Some of the rows are getting filtered in the Fact_PurchaseOrder, if they dont have supplier. You need to go for FULL OUTER JOIN for all tables, to get data for all rows of AccountPayables, irrespective of whether they have got suppliers or not.
FROM dbo.Supplier
FULL OUTER JOIN dbo.Fact_PurchaseOrder ON dbo.Supplier.supplier_key = dbo.Fact_PurchaseOrder.buyfrom_supplier_key
FULL OUTER JOIN dbo.Fact_AccountPayables ON dbo.Fact_AccountPayables.supplier_key = dbo.Supplier.supplier_key AND
dbo.Fact_AccountPayables.[PO Number] = dbo.Fact_PurchaseOrder.[Purchase Order] AND
dbo.Fact_AccountPayables.[PO Line] = dbo.Fact_PurchaseOrder.Sequence

SQL: Grouping on a subquery

I have a query where I want to aggregate column ElementAantal. However this is the first time I am grouping on columns where there is a subquery ArtikelInhoud involved.
Please your advise on how to make the query work.
SELECT
pl.[Location Code] AS Locatie,
pl.[Ending Date] AS ProdOrderDatum,
pl.[Item No_] AS Artikelnr,
pl.Description AS Artikel,
pbl.No_ AS Elementnr,
pbl.Description AS Element,
SUM(pbl.Quantity * pl.Quantity) AS ElementAantal, -----> Aggregating this column
i.[Item Category Code] AS ElementCategorie,
(
SELECT Value
FROM [$Attribute Specification] att
WHERE [Table ID] = 27 AND Code = 'INH' AND att.[Unique Record Identifier] = i1.[Unique Record Identifier]
) AS ArtikelInhoud,
i.[Gross Weight] AS ElementGewicht,
v.Name AS Leverancier
FROM [$Prod_ Order Line] pl
LEFT JOIN [$Production BOM Line] pbl ON pl.[Production BOM No_] = pbl.[Production BOM No_]
LEFT JOIN [$Item] i ON pbl.No_ = i.No_
LEFT JOIN [$Item] i1 ON pl.[Item No_] = i1.No_
LEFT JOIN [$Vendor] v ON i.[Vendor No_] = v.No_
GROUP BY pl.[Location Code],
pl.[Ending Date],
pl.[Item No_],
pl.Description,
pbl.No_,
pbl.Description,
i.[Item Category Code],
(
SELECT Value
FROM [$Attribute Specification] att
WHERE [Table ID] = 27 AND Code = 'INH' AND att.[Unique Record Identifier] = i1.[Unique Record Identifier]
),
i.[Gross Weight],
v.Name

How do I Exclude Rows When All Correlated Subqueries Return Null

I have a list of parts from a supplier and I want to see what we've bought and sold since Jan 1. I created subqueries for the sales and purchasing info.
There are four possibilities in the results:
Sales Quantity = Purchase Quantity
Sales Quantity > Purchase Quantity (including NULL Purchase Quantity)
Sales Quantity < Purchase Quantity (including NULL Sales Quantity)
Both Sales and Purchase Quantities are NULL
How do I exclude rows when both Sales and Purchase Quantity is NULL while retaining those rows which may have a NULL Sales Quantity or Purchase Quantity? An image is attached to show examples of these scenarios.
I reviewed this thread, but it does not seem to apply because my columns do not have to be equal.
SELECT DISTINCT
p21_view_supplier.supplier_id AS [Supp ID],
p21_view_supplier.supplier_name AS Supplier,
p21_view_inv_mast.item_id AS [Item ID],
p21_view_inv_mast.item_desc AS [Item Desc],
p21_view_inv_loc.location_id AS [Location ID],
invoice_data.[Total Shipped by Sales Loc],
purchase_data.[PO Qty Ordered]
FROM
p21_view_supplier
INNER JOIN p21_view_inventory_supplier ON p21_view_supplier.supplier_id = p21_view_inventory_supplier.supplier_id
INNER JOIN p21_view_inv_mast ON p21_view_inventory_supplier.inv_mast_uid = p21_view_inv_mast.inv_mast_uid
INNER JOIN p21_view_inv_loc ON p21_view_inv_mast.inv_mast_uid = p21_view_inv_loc.inv_mast_uid
--Invoices
LEFT JOIN (
SELECT
p21_view_invoice_hdr.sales_location_id,
p21_view_invoice_line.item_id,
p21_view_invoice_line.supplier_id,
p21_view_invoice_line.inv_mast_uid,
SUM(p21_view_invoice_line.qty_shipped) AS [Total Shipped by Sales Loc]
FROM
p21_view_invoice_hdr
INNER JOIN p21_view_invoice_line ON p21_view_invoice_hdr.invoice_no = p21_view_invoice_line.invoice_no
WHERE
(p21_view_invoice_hdr.invoice_date >= CONVERT(DATETIME, '2016-01-01 00:00:00', 102))
GROUP BY
p21_view_invoice_hdr.sales_location_id,
p21_view_invoice_line.item_id,
p21_view_invoice_line.supplier_id,
p21_view_invoice_line.inv_mast_uid
) invoice_data ON p21_view_supplier.supplier_id = invoice_data.supplier_id
AND p21_view_inv_mast.inv_mast_uid = invoice_data.inv_mast_uid
AND p21_view_inv_loc.location_id = invoice_data.sales_location_id
--Purchasing
LEFT JOIN (
SELECT
p21_view_po_hdr.supplier_id,
p21_view_po_hdr.location_id AS [PO Loc ID],
SUM(p21_view_po_line.qty_ordered) AS [PO Qty Ordered],
p21_view_po_line.item_id AS [Item ID],
p21_view_po_line.inv_mast_uid
FROM
p21_view_po_hdr
INNER JOIN p21_view_po_line ON p21_view_po_hdr.po_no = p21_view_po_line.po_no
WHERE
(p21_view_po_hdr.date_created >= CONVERT(DATETIME, '2016-01-01 00:00:00', 102))
AND (p21_view_po_hdr.delete_flag IS NULL OR
p21_view_po_hdr.delete_flag = 'N')
AND (p21_view_po_line.delete_flag IS NULL OR
p21_view_po_line.delete_flag = 'N')
AND (p21_view_po_line.cancel_flag IS NULL OR
p21_view_po_line.cancel_flag = 'N')
AND (p21_view_po_hdr.cancel_flag IS NULL OR
p21_view_po_hdr.cancel_flag = 'N')
GROUP BY
p21_view_po_hdr.supplier_id,
p21_view_po_hdr.location_id,
p21_view_po_line.item_id,
p21_view_po_line.inv_mast_uid
) purchase_data ON p21_view_supplier.supplier_id = purchase_data.supplier_id
AND p21_view_inv_mast.inv_mast_uid = purchase_data.inv_mast_uid
AND p21_view_inv_loc.location_id = purchase_data.[PO Loc ID]
WHERE
(p21_view_supplier.supplier_id = 8761)
AND (p21_view_inv_mast.delete_flag = 'N')
ORDER BY
p21_view_inv_mast.item_id,
p21_view_inv_loc.location_id
Assuming there is at least one not nullable column in both of the derived tables, you can simply add a condition to the outer query where clause, that will evaluate to true only if at least one of the non nullable columns in the derived tables is not null.
In this case, I'm assuming that the non-nullable column is the same for both derived tables and it's supplier_id, So I add to the where clause the following condition:
AND NOT (purchase_data.supplier_id is null and invoice_data.supplier_id is null)
The full query:
SELECT DISTINCT
p21_view_supplier.supplier_id AS [Supp ID],
p21_view_supplier.supplier_name AS Supplier,
p21_view_inv_mast.item_id AS [Item ID],
p21_view_inv_mast.item_desc AS [Item Desc],
p21_view_inv_loc.location_id AS [Location ID],
invoice_data.[Total Shipped by Sales Loc],
purchase_data.[PO Qty Ordered]
FROM
p21_view_supplier
INNER JOIN p21_view_inventory_supplier ON p21_view_supplier.supplier_id = p21_view_inventory_supplier.supplier_id
INNER JOIN p21_view_inv_mast ON p21_view_inventory_supplier.inv_mast_uid = p21_view_inv_mast.inv_mast_uid
INNER JOIN p21_view_inv_loc ON p21_view_inv_mast.inv_mast_uid = p21_view_inv_loc.inv_mast_uid
--Invoices
LEFT JOIN (
SELECT
p21_view_invoice_hdr.sales_location_id,
p21_view_invoice_line.item_id,
p21_view_invoice_line.supplier_id,
p21_view_invoice_line.inv_mast_uid,
SUM(p21_view_invoice_line.qty_shipped) AS [Total Shipped by Sales Loc]
FROM
p21_view_invoice_hdr
INNER JOIN p21_view_invoice_line ON p21_view_invoice_hdr.invoice_no = p21_view_invoice_line.invoice_no
WHERE
(p21_view_invoice_hdr.invoice_date >= CONVERT(DATETIME, '2016-01-01 00:00:00', 102))
GROUP BY
p21_view_invoice_hdr.sales_location_id,
p21_view_invoice_line.item_id,
p21_view_invoice_line.supplier_id,
p21_view_invoice_line.inv_mast_uid
) invoice_data ON p21_view_supplier.supplier_id = invoice_data.supplier_id
AND p21_view_inv_mast.inv_mast_uid = invoice_data.inv_mast_uid
AND p21_view_inv_loc.location_id = invoice_data.sales_location_id
--Purchasing
LEFT JOIN (
SELECT
p21_view_po_hdr.supplier_id,
p21_view_po_hdr.location_id AS [PO Loc ID],
SUM(p21_view_po_line.qty_ordered) AS [PO Qty Ordered],
p21_view_po_line.item_id AS [Item ID],
p21_view_po_line.inv_mast_uid
FROM
p21_view_po_hdr
INNER JOIN p21_view_po_line ON p21_view_po_hdr.po_no = p21_view_po_line.po_no
WHERE
(p21_view_po_hdr.date_created >= CONVERT(DATETIME, '2016-01-01 00:00:00', 102))
AND (p21_view_po_hdr.delete_flag IS NULL OR
p21_view_po_hdr.delete_flag = 'N')
AND (p21_view_po_line.delete_flag IS NULL OR
p21_view_po_line.delete_flag = 'N')
AND (p21_view_po_line.cancel_flag IS NULL OR
p21_view_po_line.cancel_flag = 'N')
AND (p21_view_po_hdr.cancel_flag IS NULL OR
p21_view_po_hdr.cancel_flag = 'N')
GROUP BY
p21_view_po_hdr.supplier_id,
p21_view_po_hdr.location_id,
p21_view_po_line.item_id,
p21_view_po_line.inv_mast_uid
) purchase_data ON p21_view_supplier.supplier_id = purchase_data.supplier_id
AND p21_view_inv_mast.inv_mast_uid = purchase_data.inv_mast_uid
AND p21_view_inv_loc.location_id = purchase_data.[PO Loc ID]
WHERE
(p21_view_supplier.supplier_id = 8761)
AND (p21_view_inv_mast.delete_flag = 'N')
AND NOT (purchase_data.supplier_id is null and invoice_data.supplier_id is null)
ORDER BY
p21_view_inv_mast.item_id,
p21_view_inv_loc.location_id

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

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.

SQL - query to report MAX DATE results or NULL results

I have an SQL database with 3 tables:
Customer record table, holding master data (each row is unique)
Customer notes, each note data/time stamped (there could be many notes per customer, or none at all)
Product table, showing which customer has bought which product
Table: tbl_Customer_Records
CustomerID---- Company Name-----Company Segment----- Promo Code
Table: tbl_Customer_Notes
CustomerID---- Note-----Created Date
Table: tbl_Customer_Products
CustomerID---- Product Category
What I want is to pull a list of customer records which includes the latest note only, so there are no duplicate lines if multiple notes exist. But I also want my report to include customer records if no notes exist at all. I've achieved the first part of this with a SELECT MAX function, and that works well, the problem is when I add the OR = NULL clause in the final line of code below. This doesn't work, and I can't figure out a solution.
Any suggestions will be greatly appreciated!
SELECT
[tbl_Customer_Records].[CustomerID],
[tbl_Customer_Records].[Company Name],
[tbl_Customer_Records].[Company Segment],
[tbl_Customer_Records].[Promo Code],
[tbl_Customer_Notes].[Note],
[tbl_Customer_Products].[Product Category]
FROM
tbl_Customer_Records
LEFT OUTER JOIN tbl_Customer_Notes
ON tbl_Customer_Records.CustomerID = tbl_Customer_Notes.CustomerID
LEFT OUTER JOIN tbl_Customer_Products
ON tbl_Customer_Records.CustomerID = tbl_Customer_Products.CustomerID
WHERE
[Product Category] in ('Nuts','Bolts','Screws','Spanners')
AND
[Created Date] in (SELECT MAX ([Created Date]) FROM tbl.Customer_Notes GROUP BY [CustomerID])
OR tbl_Customer_Note.Note is null
There're a few tricks to do this kind of query (row_number or join with grouped data), but I think most cleanest one in your case is to use outer apply:
select
cr.[CustomerID],
cr.[Company Name],
cr.[Company Segment],
cr.[Promo Code],
cn.[Note],
cp.[Product Category]
from tbl_Customer_Records as cr
left outer join tbl_Customer_Products as cp on cp.CustomerID = cr.CustomerID
outer apply (
select top 1
t.[Note]
from tbl_Customer_Notes as t
where t.[CustomerID] = cr.[CustomerID]
order by t.[Created_Date] desc
) as cn
where
cp.[Product Category] in ('Nuts','Bolts','Screws','Spanners')
Changed all clumsy table name.column name to alias.column name, I think it's much more readable this way.
Or:
select
cr.[CustomerID],
cr.[Company Name],
cr.[Company Segment],
cr.[Promo Code],
cn.[Note],
cp.[Product Category]
from tbl_Customer_Records as cr
left outer join tbl_Customer_Products as cp on cp.CustomerID = cr.CustomerID
left outer join tbl_Customer_Notes as cn on
cn.CustomerID = cr.CustomerID and
cn.[Created_Date] = (select max(t.[Created_Date]) from tbl_Customer_Notes as t where t.CustomerID = cr.CustomerID)
where
cp.[Product Category] in ('Nuts','Bolts','Screws','Spanners')
You can add your filter condition in ON predicate to preserve rows from left table and fetch only required matching rows from right table, from first LEFT OUTER JOIN operator. Following query should work:
SELECT
CR.[CustomerID],
CR.[Company_Name],
CR.[Company_Segment],
CR.[Promo_Code],
CN.[Note],
CP.[Product_Category]
FROM
tbl_Customer_Records CR
LEFT OUTER JOIN tbl_Customer_Notes CN
ON CR.CustomerID = CN.CustomerID AND CN.[Created_Date] in (SELECT MAX ([Created_Date])
FROM tbl_Customer_Notes
WHERE CR.CustomerID = tbl_Customer_Notes.CustomerID
GROUP BY [CustomerID])
LEFT OUTER JOIN tbl_Customer_Products CP
ON CR.CustomerID = CP.CustomerID
WHERE
[Product_Category] in ('Nuts','Bolts','Screws','Spanners')
Should work, tried with NULL values:
SELECT a.[CustomerID],
a.[Company Name],
a.[Company Segment],
a.[Promo Code],
a.[Note],
a.[Product Category]
FROM (
SELECT
cr.[CustomerID],
cr.[Company Name],
cr.[Company Segment],
cr.[Promo Code],
cn.[Note],
cp.[Product Category],
ROW_NUMBER() OVER(PARTITION BY cr.[CustomerID] ORDER BY cn.[Created Date] DESC) as rnk
FROM tbl_Customer_Records cr
LEFT JOIN tbl_Customer_Notes cn
ON cr.CustomerID = cn.CustomerID
LEFT JOIN tbl_Customer_Products cp
ON cr.CustomerID = cp.CustomerID
WHERE cp.[Product Category] in ('Nuts','Bolts','Screws','Spanners') )a
WHERE a.rnk = 1
try to use CustomerID not in (select CustomerID from tbl_Customer_Note)