SQL JOIN and WHERE statement - sql

I have a problem getting this sql statemen to return what I want:
I want it to return a list of properties both the employee or Job_Profile. If one of them do not have the property it should return NULL in that row/column
Now the sql looks like:
SELECT Parameter.Patameter_Description ParamName,
Job_Profile.Title, Job_Property.Mark JobMark,
Emp_Property.Mark EmpMark,
Emp_Id--, (Employee.First_Name + ' ' + Employee.Last_Name) EmpName
FROM Job_Property
INNER JOIN Job_Profile ON Job_Profile.Title = Job_Property.Job_Title
INNER JOIN Parameter ON Job_Property.Parameter_Id = Parameter.Id
RIGHT JOIN Emp_Property ON Emp_Property.Parameter_Id = Job_Property.Parameter_Id
INNER JOIN Employee ON Emp_Property.Emp_Id = Employee.Enterprise_Staff_Id
WHERE Employee.Enterprise_Staff_Id = 22
AND Job_Profile.Title =
(SELECT
Employee.Job_Profile_Name
FROM Employee WHERE Employee.Enterprise_Staff_Id = 22)
The result is:
Analyse test 1 3 22
And I would like it to be something like this:
Analyse test 1 3 22
Data test 3 NULL NULL or 22
economic test 4 NULL NULL or 22
Service test 2 NULL NULL or 22
I know there is a problem when I:
- join Emp_Property
- Make the WHERE statement

Try LEFT OUTER JOIN when joining Emp_Property

I found a solution, I had to make temp tables and join them:
CREATE TABLE #CompareJob
(Parameter_Id INT
,Parameter_Name VARCHAR(MAX)
,Jobprofile VARCHAR(30)
,Job_Mark INT
)
INSERT INTO #CompareJob(Parameter_Id,Parameter_Name, Jobprofile ,Job_Mark)
SELECT Parameter.Id, Parameter.Patameter_Description, Job_Profile.Title, Job_Property.Mark
FROM Job_Property
INNER JOIN Job_Profile ON Job_Profile.Title = Job_Property.Job_Title
INNER JOIN Parameter ON Job_Property.Parameter_Id = Parameter.Id
WHERE Job_Profile.Title = (SELECT Employee.Job_Profile_Name FROM Employee WHERE Employee.Enterprise_Staff_Id = 22)
CREATE TABLE #CompareEmp
(Parameter_Id INT
,Parameter_Name VARCHAR(MAX)
,Emp_Id INT
,Emp_Name VARCHAR(100)
,Emp_Mark INT
)
INSERT INTO #CompareEmp(Parameter_Id,Parameter_Name, Emp_Id , Emp_Name ,Emp_Mark)
SELECT Parameter.Id, Parameter.Patameter_Description, Employee.Enterprise_Staff_Id, (Employee.First_Name + ' ' + Employee.Last_Name) empname, Emp_Property.Mark
FROM Emp_Property
INNER JOIN Employee ON Employee.Enterprise_Staff_Id = Emp_Property.Emp_Id
INNER JOIN Parameter ON Parameter.Id = Emp_Property.Parameter_Id
WHERE Employee.Enterprise_Staff_Id = 22
SELECT * FROM #CompareJob
FULL OUTER JOIN #CompareEmp ON #CompareJob.Parameter_Id = #CompareEmp.Parameter_Id

Agree with Danny, use the 'LEFT OUTER JOIN' method instead of 'INNER JOIN' as this will only return rows where an entry is found in both tables.

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

How do you properly query the result of a complex join statement in SQL?

New to advanced SQL!
I'm trying to write a query that returns the COUNT(*) and SUM of the resulting columns from this query:
DECLARE #Id INT = 1000;
SELECT
*,
CASE
WHEN Id1 >= 6 THEN 1
ELSE 0
END AS Tier1,
CASE
WHEN Id1 >= 4 THEN 1
ELSE 0
END AS Tier2,
CASE
WHEN Id1 >= 2 THEN 1
ELSE 0
END AS Tier3
FROM (
SELECT
Org.OrgID,
App.AppID,
App.FirstName,
App.LastName,
MAX(AppSubmitU_Level.Id1) AS Id1
FROM Org
INNER JOIN AppEmployment
ON AppEmployment.OrgID = Org.OrgID
INNER JOIN App
ON App.AppID = AppEmployment.AppID
INNER JOIN AppSubmit
ON App.AppID = AppSubmit.AppID
INNER JOIN AppSubmitU_Level
ON AppSubmit.LevelID = AppSubmitU_Level.Id1
INNER JOIN AppEmpU_VerifyStatus
ON AppEmpU_VerifyStatus.VerifyStatusID = AppEmployment.VerifyStatusID
WHERE AppSubmitU_Level.SubmitTypeID = 1 -- Career
AND AppEmpU_VerifyStatus.StatusIsVerified = 1
AND AppSubmit.[ExpireDate] IS NOT NULL
AND AppSubmit.[ExpireDate] > GETDATE()
AND Org.OrgID = #Id
GROUP BY
Org.OrgID,
App.AppID,
App.FirstName,
App.LastName
) employees
I've tried to do so by moving the #Id outside the original query, and adding a SELECT(*), SUM, and SUM to the top, like so:
DECLARE #OrgID INT = 1000;
SELECT COUNT(*), SUM(employees.Tier1), SUM(employees.Tier2), SUM(employees.Tier3)
FROM
(SELECT *,
...
) AS employees
);
When I run the query, however, I'm getting the errors:
The multi-part identifier employees.Tier1 could not be bound
The same errors appear for the other identifiers in my SUM statements.
I'm assuming this has to do with the fact that the Tier1, Tier2, and Tier3 columns are being returned by the inner join query in my FROM(), and aren't values set by the existing tables that I'm querying. But I can't figure out how to rewrite it to initialize properly.
Thanks in advance for the help!
This is a scope problem: employees is defined in the subquery only, it is not available in the outer scope. You basically want to alias the outer query:
DECLARE #OrgID INT = 1000;
SELECT COUNT(*), SUM(employees.Tier1) TotalTier1, SUM(employees.Tier2) TotalTier2, SUM(employees.Tier3) TotalTier3
FROM (
SELECT *,
...
) AS employees
) AS employees;
--^ here
Note that I added column aliases to the outer query, which is a good practice in SQL.
It might be easier to understand what is going on if you use another alias for the outer query:
SELECT COUNT(*), SUM(e.Tier1), SUM(e.Tier2), SUM(e.Tier3)
FROM (
SELECT *,
...
) AS employees
) AS e;
Note that you don't actually need to qualify the column names in the outer query, since column names are unambigous anyway.
And finally: you don't actually need a subquery. You could write the query as:
SELECT
SUM(CASE WHEN Id1 >= 6 THEN 1 ELSE 0 END) AS TotalTier1,
SUM(CASE WHEN Id1 >= 4 THEN 1 ELSE 0 END) AS TotalTier2,
SUM(CASE WHEN Id1 >= 2 THEN 1 ELSE 0 END) AS TotalTier3
FROM (
SELECT
Org.OrgID,
App.AppID,
App.FirstName,
App.LastName,
MAX(AppSubmitU_Level.Id1) AS Id1
FROM Org
INNER JOIN AppEmployment
ON AppEmployment.OrgID = Org.OrgID
INNER JOIN App
ON App.AppID = AppEmployment.AppID
INNER JOIN AppSubmit
ON App.AppID = AppSubmit.AppID
INNER JOIN AppSubmitU_Level
ON AppSubmit.LevelID = AppSubmitU_Level.Id1
INNER JOIN AppEmpU_VerifyStatus
ON AppEmpU_VerifyStatus.VerifyStatusID = AppEmployment.VerifyStatusID
WHERE AppSubmitU_Level.SubmitTypeID = 1 -- Career
AND AppEmpU_VerifyStatus.StatusIsVerified = 1
AND AppSubmit.[ExpireDate] IS NOT NULL
AND AppSubmit.[ExpireDate] > GETDATE()
AND Org.OrgID = #Id
GROUP BY
Org.OrgID,
App.AppID,
App.FirstName,
App.LastName
) employees

SQL join to many rows

I have a sql Query with a lot of queries.
But i will try to make it simple
Table.Result
Id
Result
Table.ResultGender
ResultID
GenderID
Table.Gender
Id
Gender
One result can have more than one gender.
So want a result like this
Result | Gender
Some result | Female
Another result | Female, male
But i'm getting
Result | Gender
Some result | Female
Another result | male
Another result | Female
Query:
SELECT Gender.Name , Result.Result
FROM Gender
LEFT OUTER JOIN ResultGender ON Gender.Id = ResultGender.GenderId
LEFT OUTER JOIN Result ON ResultGender.ResultId = Result.Id
UPDATE
I have tried this
SELECT Gender.Name , Result.Result ,
STUFF((SELECT ',' + Name
FROM Gender
WHERE (Id = Gender_1.Id) FOR XML PATH(''))as varchar(max)) AS test
FROM Gender AS Gender_1
LEFT OUTER JOIN ResultGender ON Gender_1.Id = ResultGender.GenderId
LEFT OUTER JOIN Result ON ResultGender.ResultId = Result.Id
AND THIS in SQL manager
SELECT Gender.Name , Result.Result ,
CAST((SELECT ',' + Name
FROM Gender
WHERE (Id = Gender_1.Id) FOR XML PATH(''))as varchar(max)) AS test
FROM Gender AS Gender_1
LEFT OUTER JOIN ResultGender ON Gender_1.Id = ResultGender.GenderId
LEFT OUTER JOIN Result ON ResultGender.ResultId = Result.Id
BOTH are trying to save a RPT file
Try in following:
DECLARE #Result VARCHAR(8000)
SELECT Gender.Name, #Result = COALESCE(#Result + ', ', '') + Result.Result
FROM Gender
JOIN Result ON Gender.Id = Result.Id
JOIN ResultGender ON Gender.Id = ResultGender.GenderId
AND StudyResult.Id = ResultGender.ResultId
You are joining incorrectly. Gender.Id is the ID of a Gender record, and Result.Id is the ID of a Result record. Hence Gender.Id = Result.Id makes no sense. ResultGender is the brige table you need for the join: Gender -> GenderResult -> Result.
As to your actual request: Group by Result in order to get one record per Result. Get your Gender list with an appropriate function (I'm showing it here with MySQL's GROUP_CONCAT.)
select
r.result
group_concat(g.name)
from result r
inner join resultgender rg on rg.resultid = r.id
inner join gender g on g.id = rg.genderid
group by r.result;
Unfortunately SQL Server doesn't provide such function as GROUP_CONCAT. It needs some fumbling with XML PATH and STUFF instead. See here: How to make a query with group_concat in sql server.
In case you have Results without a Gender, use outer joins instead:
left join resultgender rg on rg.resultid = r.id
left join gender g on g.id = rg.genderid

How to merge two fields into single field using INNER JOIN

I have two tables.
**EmployeeInfo**
EmployeeName varchar(50)
EmailAddress varchar(100)
BranchID int
**BranchInfo**
BranchID int
opMgr varchar(100)
BranchMgr varchar(100)
I want a stored procedure in which if I pass email address as parameter and it should display the OpMgr and BranchMgr column from branchinfo table into single column of the relevant branch of EmployeeInfo. I am trying to write the following but no luck as i am getting multipart error.
SELECT BranchInfo.OpMgr FROM EmployeesInfo
UNION
SELECT BranchInfo.BranchMgr FROM EmployeesInfo
INNER JOIN BranchInfo ON EmployeesInfo.BranchID = BranchInfo.BranchID
WHERE AND EMPLOYEESINFO.EMAILADDRESS='john.d#mydomain.com'
Try this:
SELECT
E.EmployeeName,
E.EmailAddress,
B.BranchID,
B.BranchMgr + ' ' + B.opMgr ColName
FROM EmployeesInfo E
INNER JOIN BranchInfo B
ON E.BranchID = B.BranchID
WHERE E.EMAILADDRESS='john.d#mydomain.com'
it should display the OpMgr and BranchMgr column from branchinfo table
into single column of the relevant branch of EmployeeInfo
DECLARE #opMgr VARCHAR(100), #BranchMgr VARCHAR(100)
SELECT #opMgr = b.opMgr, #BranchMgr = b.BranchMgr
FROM EmployeeInfo e
JOIN BranchInfo b ON e.BranchID = b.BranchID
WHERE e.EMAILADDRESS='john.d#mydomain.com'
SELECT details
FROM ( VALUES (#opMgr),(#BranchMgr))
AS t(details)
you can have JOIN like this
SELECT b.opMgr + b.BranchMgr as Branch
FROM EmployeeInfo e
JOIN BranchInfo b ON b.BranchID = BranchID
WHERE e.EMAILADDRESS='john.d#mydomain.com'
Try this,
SELECT BranchInfo.OpMgr, BranchInfo.BranchMgr
FROM EmployeesInfo
INNER JOIN BranchInfo ON EmployeesInfo.BranchID = BranchInfo.BranchID
WHERE AND EMPLOYEESINFO.EMAILADDRESS = 'john.d#mydomain.com'

Output Clause: The multi-part identifier could not be bound

I am running in to the dreaded "The multi-part identifier could not be bound" error on a stored procedure I am currently working on. I have a few questions in regards to the query below.
Why am I getting this error?
Why would this error occur on ImportFundingDateTime instead of FloorplanId given that they both come from the same query, but FloorplanId is listed first in the output clause?
Can I adjust this query to not get the error while still keeping the general structure the same?
.
DECLARE #Results Table(
[FloorPlanId] UNIQUEIDENTIFIER,
[ImportFundingDateTime] DATETIME,
[TimeStamp] VARBINARY(8),
[BusinessId] UNIQUEIDENTIFIER
)
UPDATE CacRecord
SET MatchFound = 1
OUTPUT fp.[FloorplanId], cr.[ImportFundingDateTime],
fp.[TimeStamp], buyer.[BusinessId]
INTO #Results( [FloorplanId], [ImportFundingDateTime],
[TimeStamp], [BusinessId])
FROM CacRecord cr WITH (NOLOCK)
INNER JOIN CacBatch cb WITH (NOLOCK)
ON cr.CacBatchId = cb.CacBatchId
INNER JOIN Floorplan fp WITH (NOLOCK)
ON fp.UnitVIN = cr.ImportVin
AND COALESCE(fp.UnitVIN, '') <> ''
INNER JOIN Business buyer WITH (NOLOCK)
ON buyer.BusinessId = fp.BuyerBusinessId
LEFT OUTER JOIN BusinessContact bc WITH (NOLOCK)
ON bc.BusinessId = buyer.BusinessId
LEFT OUTER JOIN Contact c WITH (NOLOCK)
ON c.ContactId = bc.ContactId
WHERE cb.CacJobInstanceId = #cacJobInstanceId
AND fp.FloorplanStatusId = 1 --Approved
AND COALESCE(cr.ImportVin, '') <> ''
AND 1 =
CASE
WHEN cr.ImportFein = buyer.FederalTaxID
AND COALESCE(cr.ImportFein, '') <> '' THEN 1
WHEN cr.ImportSsn = c.Ssn
AND COALESCE(cr.ImportSsn, '') <> '' THEN 1
ELSE 0
END;
Please recheck the syntax of the OUTPUT clause OUTPUT on MSDN
Syntax
<column_name> ::=
{ DELETED | INSERTED | from_table_name } . { * | column_name }
from_table_name
Is a column prefix that specifies a table included in the FROM clause
of a DELETE or UPDATE statement that is used tospecify the rows to
update or delete.
It looks like you have aliased CacRecord in the FROM clause as "cr", but have not correlated that with the UPDATE clause.
Note: Even with it aliases in the FROM clause and NOT aliased in the UPDATE cause, SQL Server appears to recognize CacRecord as the UPDATE table, requiring you to use INSERTED instead of cr as the virtual table name.
UPDATE cr
SET MatchFound = 1
OUTPUT fp.[FloorplanId], INSERTED.[ImportFundingDateTime],
fp.[TimeStamp], buyer.[BusinessId]
INTO #Results( [FloorplanId], [ImportFundingDateTime],
[TimeStamp], [BusinessId])
FROM CacRecord cr WITH (NOLOCK)
INNER JOIN CacBatch cb WITH (NOLOCK)
ON cr.CacBatchId = cb.CacBatchId
INNER JOIN Floorplan fp WITH (NOLOCK)
ON fp.UnitVIN = cr.ImportVin
AND COALESCE(fp.UnitVIN, '') <> ''
INNER JOIN Business buyer WITH (NOLOCK)
ON buyer.BusinessId = fp.BuyerBusinessId
LEFT OUTER JOIN BusinessContact bc WITH (NOLOCK)
ON bc.BusinessId = buyer.BusinessId
LEFT OUTER JOIN Contact c WITH (NOLOCK)
ON c.ContactId = bc.ContactId
WHERE cb.CacJobInstanceId = #cacJobInstanceId
AND fp.FloorplanStatusId = 1 --Approved
AND COALESCE(cr.ImportVin, '') <> ''
AND 1 =
CASE
WHEN cr.ImportFein = buyer.FederalTaxID
AND COALESCE(cr.ImportFein, '') <> '' THEN 1
WHEN cr.ImportSsn = c.Ssn
AND COALESCE(cr.ImportSsn, '') <> '' THEN 1
ELSE 0
END;
For visitors to this question, this code block shows multiple tables being referenced in the OUTPUT clause correctly.
create table TO1 (id int, a int);
create table TO2 (id int, b int);
create table TO3 (id int, c int);
insert into TO1 select 1,1;
insert into TO2 select 1,2;
insert into TO3 select 1,3;
insert into TO3 select 1,4;
declare #catch table (a int, b int, c int)
update c
set c = a.a
output a.a, b.b, INSERTED.c
into #catch(a,b,c)
from TO1 a
inner join TO2 b on a.id=b.id
inner join TO3 c on a.id=c.id