TSQL not pulling in complete data set - sql

I have a complicated stored procedure that worked great until the client wanted to change it.
I am not great with complicated TSQL so I have no idea what is wrong with my code.
Here is the situation. I have three temp tables, Cost, Adjustments, and Payments.
In the end I merge all these tables together in a report table. The problem I am having is even if one or even two of these tables are null, as long as one table has data I need that data to show. I currently have it set up with full outer joins but I'm still not getting the full list, I'm missing probably....50 ish records that should be there.
Can anyone look at this code and tell me what the heck I'm doing wrong? I'm bringing all the data together on #ThisReportAll
UPDATE: So I removed the having clause to see what was going on, and the data for the overdue balance is returning null. So the math isn't...mathing correctly, any ideas?
CODE
CREATE TABLE #BalanceAdjustmentsAll (CustomerId int, Amount decimal(20,2));
CREATE TABLE #AnimalCostsAll (thisIndex int IDENTITY(1,1), AnimalTypeId int, Cost decimal(20,2));
CREATE TABLE #TotalAnimalCostAll (thisIndex int IDENTITY(1,1), YearSetupId int, AnimalTypeId int, AnimalType varchar(max), OwnerId int, CustomerId int, AnimalCount int, TtlSpeciesCost decimal(20,2));
CREATE TABLE #CustomerPaymentsAll (thisIndex int IDENTITY(1,1), CustomerID nvarchar(max), TtlPayments decimal(20,2));
CREATE TABLE #CustomerInfoAll (thisIndex int IDENTITY(1,1), OwnerId int, CustomerId int, FName nvarchar(200), LName nvarchar(200),BName nvarchar(200));
CREATE TABLE #ThisReportAll (thisIndex int IDENTITY(1,1), CustomerID nvarchar(max), Year char(4), OverdueBalance decimal(20,2), YearSetupId int);
INSERT INTO #BalanceAdjustmentsAll (CustomerId, Amount)
SELECT CustomerId, SUM(Amount)
FROM BalanceAdjustment
WHERE YearSetupId = 3
GROUP BY CustomerId;
/* GET Costs per Animal for 'This' yearID */
INSERT INTO #AnimalCostsAll (AnimalTypeId, Cost)
SELECT AnimalTypeId, Cost
FROM PerCapitaFee
WHERE YearSetupId = 3;
/* GET animal type totals for owner per year */
INSERT INTO #TotalAnimalCostAll (yearSetupId,AnimalTypeId,AnimalType,OwnerId,CustomerId,AnimalCount,TtlSpeciesCost)
SELECT YearSetup.YearSetupId,AnimalCount.AnimalTypeId,AnimalType.ShortDescription,Owner.OwnerId,Report.CustomerId,AnimalCount.Count,(ac.Cost * AnimalCount.Count)
FROM AnimalCount
INNER JOIN #AnimalCostsAll as ac
ON ac.AnimalTypeId = AnimalCount.AnimalTypeId
INNER JOIN AnimalType
ON AnimalCount.AnimalTypeId=AnimalType.AnimalTypeId
INNER JOIN AnimalLocation
ON AnimalLocation.AnimalLocationid=AnimalCount.AnimalLocationId
INNER JOIN Owner
ON Owner.OwnerId=AnimalLocation.OwnerId
AND Owner.OwnerType = 'P'
INNER JOIN Report
ON Report.ReportId=Owner.ReportId
INNER JOIN YearSetup
ON Report.YearSetupId=YearSetup.YearSetupId
INNER JOIN County
ON County.CountyId=AnimalLocation.CountyId
WHERE YearSetup.YearSetupId = 3 AND Report.Completed IS NOT NULL AND Report.CustomerId IS NOT NULL
/* Get The total payments a customer has made */
INSERT INTO #CustomerPaymentsAll (CustomerID,TtlPayments)
SELECT BPS.CustomerId,SUM(BPS.Amount)
FROM BatchPaymentSplit BPS
LEFT JOIN BatchPayment bp ON BPS.BatchPaymentId=bp.BatchPaymentId
LEFT JOIN Batch b ON bp.BatchId=b.BatchId
WHERE BPS.CustomerId IS NOT NULL
AND
(
((b.BatchTypeId = 'M' OR b.BatchTypeId = 'C' OR b.BatchTypeId = 'E') AND (b.BatchStatusId = 'S'))
OR
((b.BatchTypeId = 'B' OR b.BatchTypeId = 'N' OR b.BatchTypeId = 'R' OR b.BatchTypeId = 'T') AND (b.BatchStatusId = 'S' OR b.BatchStatusId='C'))
)
AND
BPS.YearSetupId = 3
GROUP BY BPS.CustomerId;
/* Deal with the name/id stuff */
INSERT INTO #CustomerInfoAll(FName, LName, BName, OwnerId, CustomerId)
SELECT
o.FirstName AS FName,
o.LastName AS LName,
o.BusinessName AS BName,
o.OwnerId AS OwnerId,
r.CustomerId AS CustomerId
FROM Owner o
INNER JOIN Report r
ON o.ReportId = r.ReportId
AND o.OwnerType = 'P'
WHERE r.CustomerId IN (SELECT CustomerId FROM #TotalAnimalCostAll)
AND r.Completed IS NOT NULL
AND r.YearSetupId = 3
AND NOT EXISTS(
SELECT 1 FROM Report
WHERE r.CustomerId = Report.CustomerId
AND Report.Completed IS NOT NULL
AND r.ReportId != Report.ReportId
AND r.YearSetupId = Report.YearSetupId
AND (
r.Completed < Report.Completed
OR (
r.Completed = Report.Completed
AND r.ReportId < Report.ReportId
)
)
)
ORDER BY CustomerId;
/** MAKE IT SO #1 **************************************************/
/* Simply Joining The Customer Info to the calculated totals to avoid any aggregation shenanigans... */
INSERT INTO #ThisReportAll (CustomerID,Year,OverdueBalance,YearSetupId)
SELECT COALESCE(t.CustomerId,cp.CustomerId,ba.CustomerID), ys.Name AS Year,
CASE
WHEN (SUM(t.TtlSpeciesCost) < 5 AND SUM(t.TtlSpeciesCost) > 0) AND (ys.Name='2015' OR ys.Name='2016')
THEN (5) - Isnull(cp.TtlPayments,0) + Isnull(ba.Amount,0)
ELSE SUM(t.TtlSpeciesCost) - Isnull(cp.TtlPayments,0) + Isnull(ba.Amount,0)
END
AS TtlOwnerCost, t.YearSetupId AS YearSetupId
FROM #TotalAnimalCostAll t
FULL OUTER JOIN #CustomerPaymentsAll cp ON t.CustomerId=cp.CustomerID
FULL OUTER JOIN #BalanceAdjustmentsAll ba ON COALESCE(t.CustomerId,cp.CustomerId)=ba.CustomerID
LEFT JOIN YearSetup ys ON COALESCE(t.CustomerId,cp.CustomerId,ba.CustomerID) = ys.YearSetupId
GROUP BY COALESCE(t.CustomerId,cp.CustomerId,ba.CustomerID),ys.Name,cp.TtlPayments, ba.Amount, t.YearSetupId
HAVING
CASE WHEN (SUM(t.TtlSpeciesCost) < 5 AND SUM(t.TtlSpeciesCost) > 0) AND (ys.Name='2015' OR ys.Name='2016')
THEN SUM(5) - Isnull(cp.TtlPayments,0) + Isnull(ba.Amount,0)
ELSE SUM(t.TtlSpeciesCost) - Isnull(cp.TtlPayments,0) + Isnull(ba.Amount,0)
END < 0;
/* Return some meaningful report data */
SELECT r.Year AS [YearName],r.CustomerID,left(ci.FName,20) AS [FirstName], left(ci.LName,40) AS [LastName], left(ci.BName,40) AS [BusinessName],r.OverdueBalance AS [Balance],r.YearSetupId
FROM #ThisReportAll r
LEFT JOIN #CustomerInfoAll ci ON r.CustomerID = ci.CustomerId
ORDER BY CAST(r.CustomerID as int) ASC;
DROP TABLE #BalanceAdjustmentsAll;
DROP TABLE #AnimalCostsAll;
DROP TABLE #TotalAnimalCostAll;
DROP TABLE #CustomerPaymentsAll;
DROP TABLE #CustomerInfoAll;
DROP TABLE #ThisReportAll;

Found it. I didn't have a default value for t.TtlSpeciesCost if it was null
SUM(t.TtlSpeciesCost) - Isnull(cp.TtlPayments,0) + Isnull(ba.Amount,0)
to
SUM(ISNULL(t.TtlSpeciesCost,0)) - Isnull(cp.TtlPayments,0) + Isnull(ba.Amount,0)

Some missing records may be found here:
by adjusting /* Get The total payments a customer has made */
INSERT INTO #CustomerPaymentsAll (CustomerID,TtlPayments)
SELECT BPS.CustomerId,SUM(BPS.Amount)
FROM BatchPaymentSplit BPS
LEFT JOIN BatchPayment bp
ON BPS.BatchPaymentId=bp.BatchPaymentId
LEFT JOIN Batch b
ON bp.BatchId=b.BatchId
AND ((b.BatchTypeId IN ('M', 'C', 'E') AND b.BatchStatusId = 'S')
OR (b.BatchTypeId IN ('B','N','R','T') AND (b.BatchStatusId IN ('S','C')))
WHERE BPS.CustomerId IS NOT NULL
AND BPS.YearSetupId = 3
GROUP BY BPS.CustomerId;
The WHERE on B would have negated the left join causing null records to be omitted. or made the left join to behave like an inner join.
To know for certain we need sample data from your tables showing which records are being omitted that you need to retain.
I also refactored the OR's and made them "IN"s to improve readability.

Related

declare table inserted values duplicated

I try to get two different table values to insert one declare table but the employee ID is duplicate,
DECLARE #WSotable TABLE
(
Employee int,
ChargedQty int,
ReturnQty int
)
--insert first table data
INSERT INTO #WSotable
SELECT DISTINCT
MD_Employee.ID,
SUM(TR_InvoiceDetails.InvoiceQuantity) AS ChargedQty,
0 AS ChargedQty
FROM
TR_SalesOrderHeader
INNER JOIN
TR_InvoiceHeader ON TR_InvoiceHeader.SalesOrderID = TR_SalesOrderHeader.ID
INNER JOIN
TR_InvoiceDetails ON TR_InvoiceDetails.InvoiceID = TR_InvoiceHeader.ID
INNER JOIN
MD_ItemMaster ON TR_InvoiceDetails.ItemID = MD_ItemMaster.ID
INNER JOIN
MD_Supplier ON MD_ItemMaster.SupplierID= MD_Supplier.ID
INNER JOIN
MD_Employee ON TR_SalesOrderHeader.CreatedBy = MD_Employee.ID
WHERE
MD_Supplier.ID = 3
AND MD_ItemMaster.ID = 572
GROUP BY
MD_Employee.ID
--insert second table data
INSERT INTO #WSotable
SELECT DISTINCT
MD_Employee.ID,
0 AS ChargedQty,
SUM(TR_SalesReturnDetails.ReturnQuantity) AS ReturnQty
FROM
TR_SalesReturnHeader
INNER JOIN
TR_SalesReturnDetails ON TR_SalesReturnDetails.SalesReturnID = TR_SalesReturnDetails.ID
INNER JOIN
MD_ItemMaster ON TR_SalesReturnDetails.ItemID = MD_ItemMaster.ID
INNER JOIN
MD_Supplier ON MD_ItemMaster.SupplierID= MD_Supplier.ID
INNER JOIN
MD_Employee ON TR_SalesReturnHeader.CreatedBy = MD_Employee.ID
WHERE
MD_Supplier.ID = 3
AND MD_ItemMaster.ID = 572
GROUP BY
MD_Employee.ID
Result:
I need to stop EmployeeID duplicates
Return the data with a final aggregation:
select Employee, sum(ChargedQty) ChargedQty, sum(ReturnQty) ReturnQty
from #WSotable
group by Employee

Duplicate Values in Query

Novice SQL user here - I am trying to determine the delivery date (de_arrdate) for an order based on event data from the events table. A shipment can have multiple events, shipments usually have 4 events so the events table will return data based on shipment ID for all 4 events. Because of this, my total $$$ is overstated. How can I return only the largest value of the shipment sequence which would essentially be the final event date? My query is below. I've also attached a sample of the current output.
select dba.disp_ship.ds_id, dba.disp_ship.ds_bill_charge,
dba.disp_ship.ds_status, dba.disp_ship.ds_ship_type,
dba.disp_events.de_site, dba.disp_events.de_arrdate,
dba.disp_events.de_shipment_id, dba.disp_events.de_ship_seq
from dba.disp_ship
inner join dba.disp_events on dba.disp_ship.ds_id = dba.disp_events.de_shipment_id
Not sure which RDBMS you are using nor the version, but if I understood correctly, you only want the amount stated in the last event of the sequence, right?
In this case, you already have the order of the events in the de_ship_seq column, so all you need to do is:
with last_event as (
select
de.de_arrdate,
de.de_shipment_id,
max(de.de_ship_seq)
from dba.disp_events as de
group by 1, 2
)
select
ds.ds_id,
ds.ds_bill_charge,
ds.de_arrdate
from dba.disp_ship as ds
join last_event as le on ds.ds_id = le.de_shipment_id
This way, you'll not get duplicity by the table disp_events, since you're only grabbing the maximum of the sequence, which it's supposed to be the last event :)
There are two ways to achieve this scenario.
1. Inner Query
select dba.disp_ship.ds_id, dba.disp_ship.ds_bill_charge,
dba.disp_ship.ds_status, dba.disp_ship.ds_ship_type,
dba.disp_events.de_site, dba.disp_events.de_arrdate,
dba.disp_events.de_shipment_id, dba.disp_events.de_ship_seq
from dba.disp_ship
inner join dba.disp_events on dba.disp_ship.ds_id = dba.disp_events.de_shipment_id,
inner Join (Select a.de_shipment_id as shipid,max(a.de_arrdate) as arrdate
from disp_events a) as t on dba.disp_events.de_shipment_id = t.shipid and dba.disp_events.de_arrdate = t.arrdate
2. Procedure
//Datatype for the Temporary tables is an assumption. Replace with your data type.
begin
declare local temporary table tbl1(
ds_id numeric(10),
ds_bill_charge numeric(14,2),
ds_status int,
ds_ship_type int,
de_site char(20),
de_arrdate date,
de_shipment_id numeric(10),
de_ship_seq numeric(10)
)on commit preserve rows;
declare local temporary table tbl1(
rowid numeric(10);
shipmentid numeric(10)
)on commit preserve rows;
declare #rowcount,#ds_id,i numeric(10);
set i = 1;
insert into tbl1
select dba.disp_ship.ds_id, dba.disp_ship.ds_bill_charge,
dba.disp_ship.ds_status, dba.disp_ship.ds_ship_type,
dba.disp_events.de_site, dba.disp_events.de_arrdate,
dba.disp_events.de_shipment_id, dba.disp_events.de_ship_seq
from dba.disp_ship
inner join dba.disp_events on dba.disp_ship.ds_id = dba.disp_events.de_shipment_id;
insert into tbl2
select number(*), ds_id from(select distinct ds_id from tbl1) a;
select count(*) into #rowcount from tbl2;
while i <= #rowcount Loop
Select ds_id into #ds_id from tbl2 where rowid = i;
delete from tbl1 where ds_id = #ds_id and
de_ship_seq not in(select top 1 de_ship_seq from tbl1 a
where a.ds_id = #ds_id order by de_arrdate desc);
i++;
end Loop;
select * from tbl1;
end
Thank You...

Insert values to a table from another table based on condition

So I have a SQL table in which I am entering values by joining other columns and entering the column values from that table.
CREATE TABLE #temp_t (id INT, cname NVARCHAR(100), val INT, aid INT)
INSERT INTO #temp_t
SELECT DISTINCT
ISNULL(IDXC.id, 0) id, sg.name + '-webApp' cName, 0 val, ag.ID aid
FROM spgroup sg
JOIN APPA APP ON sg.id > 1 AND sg.val & 4 = 0 AND APP.dagi = sg.id
JOIN AIDBI XDI ON APP.bs = XDI.bsid
LEFT JOIN #IDXC ON IDXC.agpv = sg.id
WHERE IDXC.id IS NULL
Now while inserting values to the table I need to check if sg.name exists in sysName table if yes then -webApp needs to be replaced by -andApp otherwise it remains -webApp
How can I do the same?
You can use EXISTS in a CASE expression:
SELECT DISTINCT COALESCE(i.id, 0) as id,
(sg.name +
(CASE WHEN EXISTS (SELECT 1 FROM sysname sn WHERE sn.name = sg.name)
THEN '-andApp' ELSE '-webApp'
END)
) as cName,
0 as val, ag.ID as aid
FROM spgroup sg JOIN
APPA APP
ON sg.id > 1 AND (sg.val & 4) = 0 AND APP.dagi = sg.id JOIN
AIDBI XDI
ON APP.bs = XDI.bsid LEFT JOIN
#IDXC i
ON i.IDXCsgpv = sg.id
WHERE i.id IS NULL

Left Join not matching where data exists - Temp Tabls SQL 2012

I have a query that I am using to pull in data from different tables. I have broken downthe query into a few different parts to make like a little easier. The problem is that when an ID number exists for sure in both places the LEFT JOIN does not always match them up, somtimes it does sometimes it does not.
All of the ID numbers are of type INT so I know all the data types are the same. I tried to use COLLATE SQL_Latin_General_Pref_CP1_CI_AS in the join statement but that is invalid for data of type INT was the error I received. OK fine, but I am really stuck as I don't know where to proceede from here other than dumping into excel and doing a vlookup.
Here is what I have:
DECLARE #sd DATETIME;
DECLARE #ed DATETIME;
SET #sd = '2014-01-01';
SET #ed = '2015-10-01';
DECLARE #denials_write_offs TABLE (
pk INT IDENTITY(1, 1) PRIMARY KEY
, pt_id INT
, bill_no INT
, denials FLOAT
)
INSERT INTO #denials_write_offs
SELECT a.pt_id
, a.bill_no
, a.denials_woffs
FROM (
SELECT CAST(pt_id AS INT) pt_id
, CAST(bill_no AS INT) bill_no
, SUM(tot_pay_adj_amt) AS denials_woffs
FROM smsmir.mir_pay
JOIN smsdss.c_Softmed_Denials_Detail_v
ON smsmir.mir_pay.pt_id = smsdss.c_Softmed_Denials_Detail_v.bill_no
WHERE discharged >= #sd
AND discharged < #ed
AND LEFT(smsmir.mir_pay.pay_cd, 4) = '0974'
GROUP BY pt_id
, bill_no
) A
--------------------------------------
DECLARE #EDTBL TABLE (
ACCOUNT INT
, ED_MD VARCHAR(MAX)
)
INSERT INTO #EDTBL
SELECT Z.*
FROM (
SELECT CAST(ACCOUNT AS INT) ACCOUNT
, ED_MD
FROM SMSDSS.c_Wellsoft_Rpt_tbl
) Z
----------------------------------------
DECLARE #TmpDenialsTbl TABLE (
PK INT IDENTITY(1, 1) PRIMARY KEY
, BILL_NO INT
...
...
...
)
INSERT INTO #TmpDenialsTbl
SELECT *
FROM (
SELECT bill_no
...
...
...
)
So as you can see, from the above every pt_id or bill_no is put into a table as an INT but I cannot for the life of me figure out why sometimes I get a match on my LEFT JOIN and why sometimes I do not. I did pull data from the #EDMD table and get the account number I was looking for but it did not hit on the left join below:
FROM #TmpDenialsTbl A
LEFT OUTER JOIN #denials_write_offs D
ON A.bill_no = d.pt_id
LEFT OUTER JOIN #EDTBL C
ON C.Account = D.bill_no
LEFT OUTER JOIN #USERTBL F
ON A.CERM_RVWR_ID = F.login_id
AND F.RN = 1
Example of what I am doing and what I get back
DECLARE #TmpDenials TABLE (
PT_ID INT
)
INSERT INTO #TmpDenials
SELECT A.*
FROM (
SELECT CAST(PT_ID AS INT) PT_ID
FROM SOME_TABLE
) A
DECLARE #EDMD TABLE (
PT_ID INT
EDMD VARCHAR(MAX)
)
INSERT INTO #EDMD
SELECT B.*
FROM (
SELECT CAST(PT_ID AS INT) PT_ID
EDMD
FROM SOME_OTHER_TABLE
)B
SELECT * FROM #TmpDenials
PT_ID |
123456789 |
SELECT * FROM #EDMD
PT_ID | ED_MD
123456789 | Dr. Emergency Room
SELECT *
FROM #TmpDenials A
LEFT OUTER JOIN #EDMD B
ON A.PT_ID = B.PT_ID
A.PT_ID | B.PT_ID | ED MD
123456789 | NULL | NULL
I'm not sure if this is the cause of your problem or not, but this condition is potentially suspicious:
FROM #TmpDenialsTbl A LEFT OUTER JOIN
#denials_write_offs D
ON A.bill_no = d.pt_id LEFT OUTER JOIN
#EDTBL C
ON C.Account = D.bill_no LEFT OUTER JOIN
--------^
#USERTBL F
ON A.CERM_RVWR_ID = F.login_id AND F.RN = 1
If there is no match to the C table form A, then this will always fail to match. I'm not sure if this is the intended behavior.
The other option is that a WHERE clause is filtering out the rows that you want.
Note: When you use table aliases, you should use abbreviations for the table names, so i, wo, e, and u are better than the arbitrary letters a, d, c, and f.

Error while using same table data twice during inner join

Suppose I have a table, in Database name 'Old', as below:
TABLE A
(
SeniorVehicle varchar(255),
SeniorVehicleAllowance int,
JuniorVehicle varchar(255),
JuniorVehicleAllowance int
ManagerVehicle varchar(255),
ManagerVehicleAllowance int
);
And another table, in Database name 'New' as below:
TABLE B
(
SeniorVehicle int,
SeniorVehicleAllowance int,
JuniorVehicle int,
JuniorVehicleAllowance int,
ManagerVehicle int,
ManagerVehicleAllowance int
);
I want to bring the data from TABLE A of Database 'Old' to TABLE B of Database 'New'.
The thing is that, there is a table named Vehicle in both databases as bellow:
TABLE Vehicle
(
VehicleID int pk,
VehicleName varchar(255)
)
Values in SeniorVehicle, JuniorVehicle and ManagerVehicle columns in TABLE A are the VehicleName value in TABLE Vehicle. But the value of SeniorVehicle, JuniorVehicle and ManagerVehicle that must be stored in TABLE B must be the value of VehicleID column in the Vehicle Table.
How to achieve this without error????
I have tried the following:
INSERT INTO B
(SeniorVehicle, SeniorVehicleAllowance, JuniorVehicle, JuniorniorVehicleAllowance, ManagerVehicle, ManagerVehicleAllowance)
SELECT Vehicle.VehicleID, c.SeniorVehicleAllowance, c.VehicleID, c.JuniorVehicleAllowance, c.VehicleID, c.ManagerVehicleAllowance
FROM (SELECT b.SeniorVehicle, b.SeniorVehicleAllowance, Vehicle.VehicleID, b.JuniorVehicleAllowance, b.VehicleID, b.ManagerVehicleAllowance
FROM (SELECT a.SeniorVehicle, a.SeniorVehicleAllowance, a.JuniorVehicle, a.JuniorVehicleAllowance, Vehicle.VehicleID, a.ManagerVehicleAllowance
FROM (SELECT SeniorVehicle, SeniorVehicleAllowance, JuniorVehicle, JuniorVehicleAllowance, ManagerVehicle, ManagerVehicleAllowance FROM A) as a
Inner join
Vehicle
ON a.ManagerVehicle = Vehicle.VehicleName) as b
Inner join
Vehicle
ON b.JuniorVehicle = Vehicle.VehicleName) as c
Inner join
Vehicle
ON c.SeniorVehicle = Vehicle.VehicleName
I get the following error:
The column 'VehicleID' was specified multiple times for 'c'
My Databse is MSSQL Server 2008 R2
Reformatting your current query gives:
SELECT
Vehicle.VehicleID,
c.SeniorVehicleAllowance,
c.VehicleID,
c.JuniorVehicleAllowance,
c.VehicleID,
c.ManagerVehicleAllowance
FROM (
SELECT b.SeniorVehicle,
b.SeniorVehicleAllowance,
Vehicle.VehicleID,
b.JuniorVehicleAllowance,
b.VehicleID,
b.ManagerVehicleAllowance
FROM (
SELECT a.SeniorVehicle,
a.SeniorVehicleAllowance,
a.JuniorVehicle,
a.JuniorVehicleAllowance,
Vehicle.VehicleID,
a.ManagerVehicleAllowance
FROM (
SELECT SeniorVehicle,
SeniorVehicleAllowance,
JuniorVehicle,
JuniorVehicleAllowance,
ManagerVehicle,
ManagerVehicleAllowance
FROM A
) as a
Inner join Vehicle
ON a.ManagerVehicle = Vehicle.VehicleName
) as b
Inner join Vehicle
ON b.JuniorVehicle = Vehicle.VehicleName
) as c
Inner join Vehicle
ON c.SeniorVehicle = Vehicle.VehicleName
In this query, the sub query aliased c has two columns called VehicleID (which is what your error message is telling you.
The smallest change to fix the issue is to alias the columns in the sub query, e.g:
SELECT
Vehicle.VehicleID AS SeniorVehicleId,
c.SeniorVehicleAllowance,
c.JuniorVehicleId,
c.JuniorVehicleAllowance,
c.ManagerVehicleID,
c.ManagerVehicleAllowance
FROM (
SELECT b.SeniorVehicle,
b.SeniorVehicleAllowance,
Vehicle.VehicleID AS JuniorVehicleId,
b.JuniorVehicleAllowance,
b.ManagerVehicleID,
b.ManagerVehicleAllowance
FROM (
SELECT a.SeniorVehicle,
a.SeniorVehicleAllowance,
a.JuniorVehicle,
a.JuniorVehicleAllowance,
Vehicle.VehicleID AS ManagerVehicleID,
a.ManagerVehicleAllowance
-- Rest ommited for brevity
It would be also possible to re-write the query with more joins, and omit the need for the subqueries altogether also:
SELECT srmgr.VehicleId AS SeniorVehicleId,
A.SeniorVehicleAllowance,
jrmgr.VehicleId AS JuniorVehicleId,
A.JuniorVehicleAllowance,
mgr.VehicleId AS ManagerVehicleId,
A.ManagerVehicleAllowance
FROM A
INNER JOIN Vehicle AS mgr
ON a.ManagerVehicle = mgr.VehicleName
INNER JOIN Vehicle AS jrmgr
ON a.ManagerVehicle = jrmgr.VehicleName
INNER JOIN Vehicle AS srmgr
ON a.ManagerVehicle = srmgr.VehicleName