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
Related
Have a situation where I'm trying to produce a query that shows the item # on a sales order and the total outstanding quantity across all orders. I can do this as follows:
SELECT
SL.[Item No_],
SUM(SL.[Outstanding Quantity])
FROM [Database$Sales Header] SH
LEFT JOIN [Database$Sales Line] SL ON SL.[Document No_] = SH.[No_]
LEFT JOIN [Database$Items] I ON I.[No_] = SL.[Item No_]
GROUP BY
SL.[Item No_],
SH.[Document Type],
I.[Product Code]
HAVING
SH.[Document Type] = '1'
AND I.[Product Code] = 'SHIRT'
ORDER BY
SL.[Item No_]
Above code gives me a simple summary of item # and qty. on all sales orders.
I'm using the HAVING clause to include only sales orders (Document Type)
and only items that are shirts (Product Code).
The issue I'm having is when I want to exclude a particular customer.
I tried adding: AND SH.[Customer No_] <> 'CUST1' to the HAVING clause but if I do that, then SQL will require me to add it in the GROUP BY clause. The result is I get duplicate rows where it was summarized before because now SQL is reporting on outstanding quantity by item # and customer # which is not what I want.
So I am not sure how to exclude that customer without putting it into GROUP BY.
Please use where clause to filter the data.
SELECT
SL.[Item No_],
SUM(SL.[Outstanding Quantity])
FROM [Database$Sales Header] SH
LEFT JOIN [Database$Sales Line] SL ON SL.[Document No_] = SH.[No_]
LEFT JOIN [Database$Items] I ON I.[No_] = SL.[Item No_]
where SH.[Customer No_] <> 'CUST1'
GROUP BY
SL.[Item No_],
SH.[Document Type],
I.[Product Code]
HAVING
SH.[Document Type] = '1'
AND I.[Product Code] = 'SHIRT'
ORDER BY
SL.[Item No_]
I am using 3 tables in the query: 2 with INNER JOIN and the 3rd with LEFT JOIN.
However, I am getting some NULLrecords while the LEFT JOIN condition is executing. There are coming from the Purchase line(PL_ TABLE)`which should not be the case.
Can any one recommend the change in the query to replace NULL values in the record with actual values?
Sorry, I could not find any option to attach the sample table data.
The Query
SELECT
pih.[PO Number],
pih.[Pre-Assigned No_] as [Invoice No],
pil.[Document No_],
pil.[Description] as [Reason For Discrepency],
pil.[Line No_],
pl.[No_] as [Item No],
pl.[Vendor Item No_],
pl.[Order Date],
pil.[Posting Date],
pil.[Expected Receipt Date],
pih.[Notes] as [Header Notes],
pil.[No_] as [G/L Account No],
pih.[Buy-from Vendor No_],
pih.[Buy-from Vendor Name],
Pil.Quantity as [Inv Qty From InvoiceLine],
pil.[Amount Including VAT] as [Inv Value From InvoiceLine],
pl.Quantity as [PO Quantity From Purchaseline],
pl.[Quantity Received] as [Received Qty From PurchaseLine],
pl.[Quantity Invoiced] as [Invoiced Qty From PurchaseLine] ,
pl.[Amount Including VAT] as [PO Value From PurchaseLine]
FROM
[Purch_ Inv_ Line] pil
INNER JOIN Purch_ Inv_ Header] pih
ON pil.[Document No_] = pih.[No_]
LEFT JOIN [Purchase Line] pl
ON pih.[PO Number]=pl.[Document No_] and pl.[Line No_]=pil.[Line No_]
WHERE
PIL.[Document No_] IN
(
SELECT distinct pil.[Document No_] FROM
Purch_ Inv_ Line] pil
WHERE piL.[No_] in ('700xxx','700xxx','17xxxxx') and pil.[Posting Date] >=getdate()-7
)
AND piL.[Type]='1'
There might be 2 reasons why you are getting NULL values:
Values of columns in [Purchase line] table are actually NULL
There are no matching rows in [Purchase line] table for rows that are NULL. This is how LEFT JOIN works
If you want to get only matching rows, then change LEFT JOIN to INNER JOIN - however then your result set will not contain rows from [Purch_ Inv_ Line] and [Purch_ Inv_ Header] where there are not matching [Purchase line] rows.
If you want to give default values to NULL values you can do it using ISNULL:
ISNULL(pl.[Amount Including VAT], 0) as [PO Value From PurchaseLine]
SELECT ap.ID, ap.[Adjustment Name], ap.[Adjustment Name Description], ap.[2nd Item Number], [ap].Description, ap.[Unit of Measure], ap.[Effective Date], ap.[Expired Date], MAX( ap.[Factor Value Numeric] ) , ap.[Prc Cls], ap.[Prc Cls Description], ap.[Address Number], ap.[Sales Detail Value 01], ap.[Currency Code], c.[Customer Pricing Rule], c.[Alpha Name]
FROM [Adv Price Query Export] ap
INNER JOIN ( SELECT [Adjustment Name], [2nd Item Number], MAX([Effective Date]), [Factor Value Numeric], [Sales Detail Value 01]
FROM [Adv Price Query Export] ) s ON ((s.[Adjustment Name] = ap.[Adjustment Name]) AND (s.[Effective Date] = ap.[Effective Date]) AND (s.[Sales Detail Value 01] = ap.[Sales Detail Value 01]))
INNER JOIN Customer c ON (ap.[Adjustment Name] = c.[Adjustment Schedule])
WHERE ( ap.[2nd Item Number] = "18500" OR ap.[2nd Item Number] = "185047" OR ap.[2nd Item Number] = "18550" OR ap.[2nd Item Number] = "26004" OR ap.[2nd Item Number] = "55010" )
GROUP BY ap.[Sales Detail Value 01]
Not sure where the error is but you can re-write your query like below
SELECT ap.ID,
ap.[Adjustment Name],
ap.[Adjustment Name Description],
ap.[2nd Item Number],
[ap].Description,
ap.[Unit of Measure],
ap.[Effective Date],
ap.[Expired Date],
MAX( ap.[Factor Value Numeric] ) ,
ap.[Prc Cls],
ap.[Prc Cls Description],
ap.[Address Number],
ap.[Sales Detail Value 01],
ap.[Currency Code],
c.[Customer Pricing Rule],
c.[Alpha Name]
FROM [Adv Price Query Export] ap
INNER JOIN ( SELECT [Adjustment Name],
[2nd Item Number],
MAX([Effective Date]),
[Factor Value Numeric],
[Sales Detail Value 01]
FROM [Adv Price Query Export] ) s
ON s.[Adjustment Name] = ap.[Adjustment Name]
AND s.[Effective Date] = ap.[Effective Date]
AND s.[Sales Detail Value 01] = ap.[Sales Detail Value 01]
INNER JOIN Customer c ON ap.[Adjustment Name] = c.[Adjustment Schedule]
WHERE ap.[2nd Item Number] IN ("18500", "185047", "18550", "26004", "55010" )
GROUP BY ap.[Sales Detail Value 01]
When I comment out all lines pertaining to either the "Sales Line" or "Warehouse Entry" table the query works as expected. But when I use this query as is; it returns faulty(unrealistically high by at least 5 digits) data.
The idea is to iterate the "Item" table and to obtain the amount in stock as well as the sum of quantity sold as well as It's worth. I think there must be something wrong by the way I'm joining these tables. Both "Warehouse Entry" and "Sales Line" table have multiple entries that can be linked to I.[No_].
USE NAV2009_R2_SHOWTEX_LIVE
SELECT I.[No_]
,sum(S.[Quantity (Base)]) AS [Quantity Sold]
,min(I.[IP Total (Manual)]) * sum(WE.[Quantity]) AS [Stock Value]
,sum(WE.[Quantity]) AS [Quantity Stock]
FROM [Item] AS I
INNER JOIN [Warehouse Entry] AS WE ON WE.[Item No_] = I.[No_]
AND WE.[Location Code] = 'BU'
AND WE.[Bin Code] <> 'SHIPPING'
AND WE.[Bin Code] <> 'WORKSHOP'
AND WE.[Bin Code] <> 'OUTBOX'
AND WE.[Bin Code] <> 'CUT'
AND WE.[Bin Code] <> 'VERZEND'
INNER JOIN [Sales Line] AS S ON S.[No_] = I.[No_]
AND S.[Shipment Date] > '07/01/2015'
AND S.[Document Type] = 1
WHERE I.[No_] LIKE '140003000007'
GROUP BY I.[No_]
Sample Data
No.|Quantity Sold|Stock Value|Quantity Stock
Wrong Data
140003000007|204484537.36000000000000000000|13051602.124400| 2355884.86000000000000000000
Right Data
140003000007|61703.24000000000000000000|13623.801800|2459.17000000000000000000
SELECT sumQuantityBase as [Quantity Sold],
minIP * sumQuantityBase as [Stock Value],
sumQuantityBase as [Quantity Stock]
FROM
(SELECT MIN(I.[IP Total (Manual)] )as minIP,
No_
FROM I
WHERE [No_] like '140003000007'
GROUP BY No_) MinI INNER JOIN
(SELECT SUM([Quantity]) as sumQuantity,
[Item No_]
FROM WE
WHERE [Location Code] = 'BU'
AND [Bin Code] <> 'SHIPPING'
AND [Bin Code] <> 'WORKSHOP'
AND [Bin Code] <> 'OUTBOX'
AND [Bin Code] <> 'CUT'
AND [Bin Code] <> 'VERZEND'
GROUP BY [Item No_] ) SumWE
ON MinI.[No_] = SumWE[Item No_] INNER JOIN
(SELECT SUM([Quantity (Base)]) as sumQuantityBase,
No_
FROM S
WHERE [Shipment Date] > '07/01/2015'
AND [Shipment Date] IS NOT NULL
AND [Document Type] = 1
GROUP BY No_ ) SumS
ON SumS.[No_] = MinI.[No_]
Try this one. When you want to aggregate data using sum or min function i'd recommend you do it in a subset. that way you keep it simple
I have two separate queries here that I need to make into one query, I'll post the queries, then try to explain what I'm trying to do.
SELECT Distinct I.ITMCDE, V.VNDRCDE, V.VNAME
FROM (SELECT RIGHT(Items.[Item Number], 3) as ITMCDE FROM Items) I,
(SELECT LEFT(Vendors.[Vendor ID], 3) as VNDRCDE,
Vendors.[Vendor Name] as VNAME
FROM Vendors) V
WHERE I.ITMCDE = V.VNDRCDE
In this first one, I simply match up the vendor code with the item code, to get the vendor name that produces the item.
SELECT DISTINCT (Items.[Item Description]), ItemQuantities.[QTY Available],
Items.[Selling U Of M], Items.[Item Number]
FROM ItemQuantities
INNER JOIN Items ON ItemQuantities.[Item Number] = Items.[Item Number]
WHERE Items.[Item Number] LIKE 'WH%'
AND Items.[Item Number] NOT LIKE '%RMW'
In this second one I'm selecting the item description, quantity available from two separate tables (quantity available is in a different table, match them up using the item number)
As you can see, the only correlation between the three tables is the item number, and not even that in the vendors table. The last three characters of the item number correlate with the first three characters of the vendor id... I did not design this setup. I'm just trying to work with it now.
How do I join these two statements into one single statement that will give me the vendor name, item description, Unit of Measure (Selling U of M), and item quantity where the item description is unique?
I think this should work:
SELECT DISTINCT Items.[Item Description],
ItemQuantities.[QTY Available],
Items.[Selling U Of M],
Items.[Item Number],
V.VNAME
FROM ItemQuantities
INNER JOIN Items ON ItemQuantities.[Item Number] = Items.[Item Number]
INNER JOIN Vendors ON
RIGHT(Items.[Item Number], 3) = LEFT(Vendors.[Vendor ID], 3)
WHERE Items.[Item Number] LIKE 'WH%'
AND Items.[Item Number] NOT LIKE '%RMW'
You can join it in:
SELECT DISTINCT (i.[Item Description]), iq.[QTY Available],
i.[Selling U Of M], i.[Item Number],
V.VNDRCDE, V.VNAME
FROM ItemQuantities iq INNER JOIN
Items i
ON iq.[Item Number] = i.[Item Number] left outer join
Vendors v
on LEFT(v.[Vendor ID], 3) = RIGHT(i.[Item Number], 3)
WHERE i.[Item Number] LIKE 'WH%' and
i.[Item Number] NOT LIKE '%RMW'
I am not sure if you intend anything special with the parentheses around i.[Item Description]. The distinct keyword applies to the entire row.
If you want distinct only on the description, then you need to use group by. Something like:
SELECT i.[Item Description],
max(iq.[QTY Available]),
max(i.[Selling U Of M]), max(i.[Item Number]),
max(V.VNDRCDE), max(V.VNAME)
FROM ItemQuantities iq INNER JOIN
Items i
ON iq.[Item Number] = i.[Item Number] left outer join
Vendors v
on LEFT(v.[Vendor ID], 3) = RIGHT(i.[Item Number], 3)
WHERE i.[Item Number] LIKE 'WH%' and
i.[Item Number] NOT LIKE '%RMW'
group by i.[Item Description])
The max() will return the maximum value. If all are the same, then this is a good way to get an "arbitrary" value.
#sgeddes Thank you.
This is what I came up with
SELECT DISTINCT
Item.ITEMNMBR AS [Item Number],
Item.ITEMDESC AS [Item Description],
Item.ITMGEDSC AS [Item Category],
Item.SELNGUOM AS [Unit of Measure],
(SELECT VENDNAME FROM PM00200 WHERE (VENDORID = IV00103.VENDORID)) AS [Vendor Name],
(CASE WHEN Quan.QTYONHND > 0 THEN 'In Stock' ELSE 'Out of Stock' END) AS [Stock Status]
FROM IV00101 AS Item INNER JOIN
IV00102 AS Quan ON Item.ITEMNMBR = Quan.ITEMNMBR INNER JOIN
IV00103 ON Item.ITEMNMBR = IV00103.ITEMNMBR AND Quan.ITEMNMBR = IV00103.ITEMNMBR
WHERE (Item.ITEMNMBR LIKE 'WH%') AND (IV00103.VENDORID NOT LIKE '%MIL')