Unexpected NULLs in JOIN query - sql

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]

Related

How to Filter Data in SQL Without Using Group By / Having Functions

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_]

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

How to SQL join payments with invoices in NAV Dynamics (former Navision)

The question is about SQL fiddling in Dynamics Nav tables, especially the table [$Vendor Ledger Entry]. How to link each payment to appropriate invoices.
The aim is to get [External Document No_] and [Amount] of the invoice. One payment can be matched with many invoices (happens) or one invoice with many payments (rare case).
My desperate approach is:
;with cte as
(
select
*
,[Row_max]=max([Row]) OVER(PARTITION BY CBEN,[Document Type])
from (
select
*
,[Row]=ROW_NUMBER() OVER(PARTITION BY CBEN,[Document Type] ORDER BY [Entry No_] asc)
from (
select
*
,CBEN=case when [Closed by Entry No_]=0 then [Entry No_] else [Closed by Entry No_] end
from [CompanyName$Vendor Ledger Entry] --here put correct table name
) tb1
) tb2
)
select
a.[Entry No_] [Entry No_payment] -- letter t means transfers
,b.[Entry No_] [Entry No_invoice] -- letter p means payables
--,a.CBEN as CBEN_t
--,b.CBEN as CBEN_p
--,a.[Row_max] as Row_max_t
--,b.[Row_max] as Row_max_p
--,a.[Row] as Row_t
--,b.[Row] as Row_p
,a.[Open]
,b.[External Document No_] [External Document No_invoice]
,a.[Document No_] [Document No_payment]
,b.[Document No_] [Document No_invoice]
,b.[Document Date]
,b.[Posting Date]
,b.[Due Date]
,Amount_p=b.[Closed by Amount]
--,a.[Company]
from cte a
left join cte b
on
(
a.CBEN=b.CBEN and -- join using Closed By Entry No
(a.[Row]=b.[Row] and a.[Row_max]=b.[Row_max] or
a.Row_max=1 and not (a.[Row_max]>1 and b.[Row_max]>1) or
b.Row_max=1 and not (a.[Row_max]>1 and b.[Row_max]>1)
) and
a.[Document Type] in (0,1) and
b.[Document Type]=2
and a.[Open]=0
)
or
(
a.CBEN = b.[Entry No_] and -- or join by Closed By Entry No to EntryNo
(a.[Row]=b.[Row] and a.[Row_max]=b.[Row_max] or
a.Row_max=1 and not (a.[Row_max]>1 and b.[Row_max]>1) or
b.Row_max=1 and not (a.[Row_max]>1 and b.[Row_max]>1)
) and
a.[Document Type] in (0,1) and
b.[Document Type]=2
and a.[Open]=0
)
where
a.[Open]=0 and a.[Document Type] in (0,1) and b.[Entry No_] is not null -- show payments with matched invoices
or
a.[Open]=1 and a.[Document Type] in (0,1) and b.[Entry No_] is null -- or payments with open status
order by a.CBEN,1,2,a.[Document No_]
I am at a loss to join Invoice [Amount] and I do not know in which Dynamics NAV table it might be.
the table is
[Detailed Vendor Ledg. Entry]
with [Entry Type] = Application

How do i sum data from 2 tables left joined to 1 table?

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

Returning Multiples of SUM when joining two tables

When I join these two tables the sum results are multiples of the number of rows in the tables being queried. For instance, sum(jle.Unit Price) should be $834,485.00. However, it returns a value of $7760710.50. It is summing the lines from that table 31 times, the same number, minus one, of rows in the jpl table. The same for the sum on jpl.[Total Price]. Returning 3 times (for the three rows in jle table) than the result should be. What am I doing wrong. I want to add this to a query that is already working based on the Job No_ field.
select jle.[Job No_], sum(jle.[Unit Price]) as 'Invoiced Amount', sum(jpl.[Total Price])as 'Sale $'
from [Job Ledger Entry] jle join [Job Planning Line] jpl on jle.[Job No_] = jpl.[Job No_]
where jle.[Job No_] = 'j-2397'
group by jle. [Job No_]
Try this.
select jpl.[Job No_], SUM(jle.[Unit Price]) as 'Invoiced Amount', MIN(jpl.[Total Price]) AS 'Sale $'
from [Job Planning Line] jpl INNER JOIN (SELECT DISTINCT [Job No_], [Unit Price] FROM [Job LEdger Entry]) AS jle on jle.[Job No_] = jpl.[Job No_]
where jpl.[Job No_] = 'j-2397'
group by jpl. [Job No_]