SQL selecting not surely existing column from on table or another - sql

I use generalisation/specialize table Zadavatel (which contains primary key) as either table Sukromna_osoba or Firma (both contains foreign key that points on Zadavatel).
I need to select Sukromna_osoba table if Sukromna_osoba.meno = 'string' exists or Firma table if Firma.nazov_firmy = 'string' exists, both if both conditions are true. I also need this to be in one select.
CREATE TABLE Zadavatel (
id_zadavatela INTEGER,
adresa VARCHAR(25)
);
CREATE TABLE Sukromna_osoba (
id_sukromnej_osoby INTEGER,
meno VARCHAR(20),
mobil INTEGER,
email VARCHAR(20)
);
CREATE TABLE Firma (
id_firmy INTEGER,
nazov_firmy VARCHAR(20),
ico INTEGER,
bankove_spojenie INTEGER
);
id_zadavatela is primary key, and id_sukromnej_osoby and id_firmy are foreign keys which points at id_zadavatela.
I tried something like this:
SELECT PR.id_projektu, PR.popis, ZAD.id_zadavatela, FI.nazov_firmy
FROM Projekt PR JOIN Zamestnanec ZAM ON PR.manazer = ZAM.osobne_cislo
JOIN Zadavatel ZAD ON PR.zadavatel = ZAD.id_zadavatela
JOIN Firma FI ON ZAD.id_zadavatela = FI.id_firmy
WHERE ZAM.meno = 'Jan Novák' OR (
SELECT PR1.id_projektu, PR1.popis, ZAD1.id_zadavatela, SO1.meno
FROM Projekt PR1 JOIN Zamestnanec ZAM1 ON PR1.manazer = ZAM1.osobne_cislo
JOIN Zadavatel ZAD1 ON PR1.zadavatel = ZAD1.id_zadavatela
JOIN Sukromna_osoba SO1 ON ZAD1.id_zadavatela = SO1.id_sukromnej_osoby
WHERE ZAM1.meno = 'Jan Novák'
)

Since you do not know if it's a firm or a person, you could use left outer join on both, like this:
SELECT PR.id_projektu, PR.popis, ZAD.id_zadavatela, FI.nazov_firmy, SO.meno
FROM Projekt PR
JOIN Zamestnanec ZAM ON PR.manazer = ZAM.osobne_cislo
JOIN Zadavatel ZAD ON PR.zadavatel = ZAD.id_zadavatela
LEFT OUTER JOIN Firma FI ON ZAD.id_zadavatela = FI.id_firmy
LEFT OUTER JOIN Sukromna_osoba SO ON ZAD.id_zadavatela = SO.id_sukromnej_osoby
WHERE ZAM.meno = 'Jan Novák'
One of the two result columns, nazov_firmy or meno, will be NULL.

Related

Problem with creating a SQL view with multiple joins

I am trying to create a view which will be a base for Excel export in API. Basically, what it contains is information about particular projects. To said projects calculations can be added (it all happens on the form on frontend). Those calculations are called EBIT, EBIT+ and OVI. User can add either one, two or all of them, so for example there will be projects with only EBIT, but also projects with only for example EBIT, but also only with EBIT+ and OVI. View needs to return the project information with all chosen calculations in one row, so because some type of calculations wont be chosen by user there needs to be a type safety as well.
Code of my view:
CREATE VIEW [Signoff].[ExecelReport_uvw]
AS SELECT
project.ProjectName,
project.CreatedOn,
project.ProjectId,
subCategory.SubCategoryName,
projectStatus.StatusName,
overallCategory.CategoryName,
projectUserResponsible.UserName,
valueImprovementType.ValueImprovementTypeName,
OVI.OverallImprovementTypeName,
project.NameOfSuplier,
improvementCalculation.Baseline,
improvementCalculation.ImpactValue,
project.ContractStartDate,
project.ContractEndDate,
userbusinessController.UserName as businessControllerName,
businessControllerStatus.ApprovalStatusName businessControllerStatus,
userbusinesOwner.UserName as businessOwnerName,
businesOwnerStatus.ApprovalStatusName as businessOwnerStatus,
userbusinessCFO.UserName as businessCFOName,
businessCFOStatus.ApprovalStatusName as businessCFOStatus,
project.IsEbitda,
improvementCalculation.EBITDA
FROM [Signoff].[Project] as project
LEFT JOIN [Signoff].[OverallImprovementType] as OVI on project.OverallImprovementTypeId = OVI.OverallImprovementTypeId
LEFT JOIN [Signoff].[SubCategory] as subCategory on project.GPSubCategory = subCategory.SubCategoryId
LEFT JOIN [Signoff].[Category] as overallCategory on project.GPCategory = overallCategory.CategoryId
LEFT JOIN [Signoff].[ValueImprovementType] as valueImprovementType on project.ValueImprovementTypeId = valueImprovementType.ValueImprovementTypeId
LEFT JOIN [Signoff].[Status] as projectStatus on project.ProjectStatus = projectStatus.StatusId
LEFT JOIN [Signoff].[User] as projectUserResponsible on project.ProjectResponsible = projectUserResponsible.UserId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessControler on project.ProjectId = projectUserbusinessControler.ProjectId AND projectUserbusinessControler.ProjectRoleId = 'A36FC6CD-9ED7-4AA8-B1BE-355E48BDE25A'
LEFT JOIN [Signoff].[User] as userbusinessController on projectUserbusinessControler.ApproverId = userbusinessController.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businessControllerStatus on projectUserbusinessControler.ApprovalStatusId = businessControllerStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessOwner on project.ProjectId = projectUserbusinessOwner.ProjectId AND projectUserbusinessOwner.ProjectRoleId = 'E1E23E4F-1CA4-4869-9387-43CEDAEBBBB0'
LEFT JOIN [Signoff].[User] as userbusinesOwner on projectUserbusinessOwner.ApproverId = userbusinesOwner.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businesOwnerStatus on projectUserbusinessOwner.ApprovalStatusId = businesOwnerStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessCFO on project.ProjectId = projectUserbusinessCFO.ProjectId AND projectUserbusinessCFO.ProjectRoleId = 'DA17CF66-1D61-460E-BF87-5D86744DF22A'
LEFT JOIN [Signoff].[User] as userbusinessCFO on projectUserbusinessCFO.ApproverId = userbusinessCFO.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businessCFOStatus on projectUserbusinessCFO.ApprovalStatusId = businessCFOStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectImprovementCalculation] as projectImprovementCalculation on project.ProjectId = projectImprovementCalculation.ProjectId
LEFT JOIN [Signoff].[ImprovementCalculation] as improvementCalculation on projectImprovementCalculation.ImprovementCalculationId = improvementCalculation.ImprovementCalculationId
Improvement calculation table:
CREATE TABLE [Signoff].[ImprovementCalculation]
(
[ImprovementCalculationId] INT NOT NULL IDENTITY,
[Baseline] INT NOT NULL,
[TotalSpend] INT NOT NULL,
[ImpactValue] INT NOT NULL,
[ImpactPercentage] INT NOT NULL,
[EBITDA] INT NOT NULL,
[CalculationType] VARCHAR (255) NOT NULL
)
GO
ALTER TABLE [Signoff].[ImprovementCalculation]
ADD CONSTRAINT [PK_ImprovemntCalculation] PRIMARY KEY([ImprovementCalculationId]);
GO
Project Improvement Calculation table:
CREATE TABLE [Signoff].[ProjectImprovementCalculation]
(
[ProjectImprovementCalculationId] INT NOT NULL IDENTITY,
[ProjectId] UNIQUEIDENTIFIER NOT NULL,
[ImprovementCalculationId] INT NOT NULL,
)
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT [PK_ProjectImprovementCalculation] PRIMARY KEY([ProjectImprovementCalculationId]);
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT FK_ProjectProjectImprovementCalculation
FOREIGN KEY (ProjectId) REFERENCES [Signoff].[Project](ProjectId);
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT FK_ImprovementCalculationProjectImprovementCalculation
FOREIGN KEY (ImprovementCalculationId) REFERENCES [Signoff].[ImprovementCalculation](ImprovementCalculationId);
GO
Just in case, although I don't think it's needed, the project table:
CREATE TABLE [Signoff].[Project]
(
[ProjectId] UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID()),
[ProjectName] NVARCHAR(50) NOT NULL,
[LegalEntity] UNIQUEIDENTIFIER NOT NULL,
[ValueImprovementTypeId] INT NOT NULL,
[OverallImprovementTypeId] INT NOT NULL,
[NameOfSuplier] NVARCHAR(50) NOT NULL,
[ContractStartDate] DATE NOT NULL,
[ContractEndDate] DATE NOT NULL,
[GPCategory] UNIQUEIDENTIFIER NOT NULL,
[GPSubCategory] UNIQUEIDENTIFIER NOT NULL,
[ProjectResponsible] UNIQUEIDENTIFIER NOT NULL,
[ProjectNumber] INT,
[FullProjectNumber] VARCHAR(55),
[ProjectStatus] UNIQUEIDENTIFIER NOT NULL DEFAULT '05c2f392-8b69-4915-a166-c4418889f9e8',
[IsCanceled] BIT NULL DEFAULT 0,
[IsEbitda] BIT NOT NULL DEFAULT 0,
[CreatedOn] DATETIME NOT NULL DEFAULT SYSDATETIME()
)
GO
ALTER TABLE [Signoff].[Project]
ADD CONSTRAINT [PK_Project] PRIMARY KEY([ProjectId]);
GO
ALTER TABLE [Signoff].[Project]
ADD CONSTRAINT [FK_ProjectStatus] FOREIGN KEY ([ProjectStatus]) REFERENCES [Signoff].[Status]([StatusId]);
GO
I have so came up with this solution, but it returns every single calculation in a different row in a table, and I want all calculations be in a single row with a project, so not what I am looking for:
LEFT JOIN [Signoff].[ProjectImprovementCalculation] as projectImprovementCalculation on project.ProjectId = projectImprovementCalculation.ProjectId
LEFT JOIN [Signoff].[ImprovementCalculation] as improvementCalculation on projectImprovementCalculation.ImprovementCalculationId = improvementCalculation.ImprovementCalculationId
Does anyone knows how to do it? Or I am approaching a problem from completely wrong way? If the information I have written is a bit chaotic, something isn't understandable, I can rephrase it.
I will assume that the available CalculationType values is fixed, that each project will have at most one improvement calculation per type, and that you wish to define fixed dedicated columns for BaseLine and ImpactValue each calculation type.
One approach is to use nested joins that will effectively LEFT JOIN the INNER JOINed combination of ProjectImprovementCalculation and ImprovementCalculation once for each calculation type. The results of each can then be referenced individually in the final select list.
Something like:
SELECT ...
IC_AAA.BaseLine, IC_AAA.ImpactValue,
IC_BBB.BaseLine, IC_BBB.ImpactValue,
...
FROM ...
LEFT JOIN Signoff.ProjectImprovementCalculation as PIC_AAA
JOIN Signoff.ImprovementCalculation as IC_AAA
ON IC_AAA.ImprovementCalculationId = PIC_AAA.ImprovementCalculationId
AND IC_AAA.CalculationType = 'AAA'
ON PIC_AAA.ProjectId = project.ProjectId
LEFT JOIN Signoff.ProjectImprovementCalculation as PIC_BBB
JOIN Signoff.ImprovementCalculation as IC_BBB
ON IC_BBB.ImprovementCalculationId = PIC_BBB.ImprovementCalculationId
AND IC_BBB.CalculationType = 'BBB'
ON PIC_BBB.ProjectId = project.ProjectId
...
The syntax is somewhat odd with two JOINs followed by two ON clauses. It would be clearer if parentheses were allowed, but (as far as I know) that is not part of the syntax.
There are several alternatives that accomplish the same. The following uses an OUTER APPLY:
SELECT ...
AAA.BaseLine, AAA.ImpactValue,
BBB.BaseLine, BBB.ImpactValue,
...
FROM ...
OUTER APPLY (
SELECT IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
AND IC.CalculationType = 'AAA'
WHERE PIC.ProjectId = project.ProjectId
) AAA
OUTER APPLY (
SELECT IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
AND IC.CalculationType = 'BBB'
WHERE PIC.ProjectId = project.ProjectId
) BBB
...
Using a Common Table Expression (CTE) can reduce some of the duplication as well as making the query a bit more readable.
;WITH ImprovementCTE AS (
SELECT PIC.ProjectId, IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
)
SELECT ...
AAA.BaseLine, AAA.ImpactValue,
BBB.BaseLine, BBB.ImpactValue,
...
FROM ...
LEFT JOIN ImprovementCTE AAA
ON AAA.ProjectId = project.ProjectId
AND AAA.CalculationType = 'AAA'
LEFT JOIN ImprovementCTE BBB
ON BBB.ProjectId = project.ProjectId
AND BBB.CalculationType = 'BBB'
...
You might also try using conditional aggregation in a single CROSS APPLY:
SELECT ...
IC.BaseLineAAA, IC.ImpactValueAAA,
IC.BaseLineBBB, IC.ImpactValueBBB,
...
FROM ...
CROSS APPLY (
SELECT
BaseLineAAA = SUM(CASE WHEN IC.CalculationType = 'AAA' THEN IC.BaseLine),
ImpactValueAAA = SUM(CASE WHEN IC.CalculationType = 'AAA' THEN IC.ImpactValue),
BaseLineBBB = SUM(CASE WHEN IC.CalculationType = 'BBB' THEN IC.BaseLine),
ImpactValueBBB = SUM(CASE WHEN IC.CalculationType = 'BBB' THEN IC.ImpactValue),
...
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
WHERE PIC.ProjectId = project.ProjectId
) IC
I expect there are additional approaches such as using a PIVOTs.
If the above appears to suit your needs, you should still run tests and examine the execution plans to see which performs best. Some may have a tendency to retrieve all ImprovementCalculation rows even when a subset of projects are selected.
To handle missing calculation types, you can use the ISNULL() function to provide a default. If you need to force a blank value in an otherwise numeric result, you might need to use something like ISNULL(CONVERT(VARCHAR(50), result), '').

How to use Left Join in subquery SQL Server?

I am trying to use left join in subquery in SQL Server. My query looks fine to me but it gives syntax error.
This is my query:
(
SELECT
FK_OrderNo AS LHNo, VendorName AS LHVendor
FROM
tbl_ShipmentAPAR
LEFT JOIN
tbl_vendors ON FK_VendorID = VendorID
WHERE
FK_ServiceID = 'LH'
) LHBase ON PK_OrderNo = LHNo
LEFT JOIN
(SELECT
FK_OrderNo AS DANo,
VendorName AS DAVendor
FROM
tbl_ShipmentAPAR
LEFT JOIN
tbl_vendors ON FK_VendorId = VendorId
WHERE
FK_ServiceId = 'DA') DABase ON PK_OrderNo = DANo
This is the error I'm getting:
This is my table structure:
CREATE TABLE tbl_ShipmentAPAR
(
VendorID int PRIMARY KEY,
VendorName varchar(200),
FK_OrderNo int
)
CREATE TABLE tbl_vendors
(
FK_VendorID int,
FOREIGN KEY (FK_VendorID) REFERENCES tbl_ShipmentAPAR(VendorID),
FK_ServiceID varchar(200)
)
INSERT INTO tbl_ShipmentAPAR VALUES (1, 'John',123)
INSERT INTO tbl_vendors VALUES (1,'LH')
As #Chris mentioned, the query is bit incomplete. I guess you are trying to do something like this:
SELECT * FROM /*--> Added new */
(
SELECT
FK_OrderNo AS LHNo, VendorName AS LHVendor
FROM
tbl_ShipmentAPAR
LEFT JOIN
tbl_vendors ON FK_VendorID = VendorID
WHERE
FK_ServiceID = 'LH'
) LHBase
LEFT JOIN
(SELECT
FK_OrderNo AS DANo,
VendorName AS DAVendor
FROM
tbl_ShipmentAPAR
LEFT JOIN
tbl_vendors ON FK_VendorId = VendorId
WHERE
FK_ServiceId = 'DA') DABase ON LHBase.LHNo = DABase.DANo /* -->Modified PKOrder no to LHNo because PKOrder no doesn't exist in either of the sub-queries */
This query worked for me. Comment to this answer if something must be changed.

Postgresql UPDATE LEFT JOIN

So, I have the following code that updates a language string table, based on an id, and a language code. If I perform a SELECT using the same from expression, it selects just one row. If I do update, it updates all rows. Where am I going wrong with this?
UPDATE shopmaster.catalog_lang SET shortname='TEST'
FROM shopmaster.catalog_lang cl LEFT JOIN shopmaster.lang l ON cl.langid=l.langid
WHERE cl.catalogid=7 AND l.code='fr';
Here's the definition of the two tables:
CREATE TABLE IF NOT EXISTS shopmaster.lang(
langid SERIAL,
name TEXT,
code TEXT,
active BOOLEAN,
donotdelete BOOLEAN,
PRIMARY KEY (langid)
CREATE TABLE IF NOT EXISTS shopmaster.catalog_lang(
catalogid INT references shopmaster.catalog(catalogid),
langid INT references shopmaster.lang(langid),
title TEXT,
shortname TEXT,
dirname TEXT,
PRIMARY KEY (catalogid, langid)
);
Don't repeat the table being updated in the FROM. So:
UPDATE shopmaster.catalog_lang cl
SET shortname = 'TEST'
FROM shopmaster.lang l
WHERE cl.langid = l.langid AND cl.catalogid = 7 AND l.code = 'fr';
In Postgres each reference to the table is separate. Your update is equivalent to this SELECT:
SELECT . . .
FROM shopmaster.catalog_lang CROSS JOIN
shopmaster.catalog_lang cl LEFT JOIN
shopmaster.lang l
ON cl.langid = l.langid
WHERE cl.catalogid = 7 AND l.code = 'fr';
And this is definitely not what you intend.

Convert SQLite join with multiple tables to PostgreSQL

I have this dictionary thing and the table with translations. I can do a nice select using it with SQLite
SELECT e.slug,
en.title,
en.locale
FROM entities AS e
LEFT JOIN (
locales AS en,
entity_locales AS el
) ON (
el.entity_id = e.id
AND el.locale_id = en.id
AND en.locale == 'en'
)
That produces:
present, translation, en
missing, NULL, NULL
But I can't convert it to Postgres because I don't understand what is going on when you specify more than one table in LEFT JOIN in SQLite:
SELECT e.slug,
en.title,
en.locale
FROM entities e
LEFT JOIN entity_locales el ON (el.entity_id = e.id)
JOIN locales en ON (
el.locale_id = en.id
AND en.locale = 'en'
)
Produces only
present, translation, en
Is there a way to make it work?
Database structure in SQLite format:
CREATE TABLE IF NOT EXISTS "entities" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"slug" varchar
);
CREATE TABLE IF NOT EXISTS "entity_locales" (
"entity_id" integer,
"locale_id" integer
);
CREATE TABLE IF NOT EXISTS "locales" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"title" varchar,
"locale" varchar
);
insert into entities(id, slug) values(1, 'present');
insert into entities(id, slug) values(2, 'missing');
insert into locales(id, title, locale) values(1, 'translation', 'en');
insert into entity_locales(entity_id, locale_id) values(1, 1);
You are using a left join only to the second table, and then you are using an inner join to the third. You need to use a left join to the product of the inner join between the second and third table.
Try this instead:
SELECT e.slug,
en.title,
en.locale
FROM entities e
LEFT JOIN
(
entity_locales el
JOIN locales en ON (
el.locale_id = en.id
AND en.locale = 'en'
)
) ON (el.entity_id = e.id)
btw, your initial script mixes implicit and explicit joins. I would advise against using implicit joins since explicit joins are a standard part of SQL for over 25 years now.

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