How to join two table based on condition? - sql-server

There are three table A,B,C
A table columns are Name,ID,Address
B table columns are ID,Address,School
C table columns are School,address,cafe
If Name='A'
Then Table A and Table B will join based on A.ID =B.ID
IF Name='B'
Then Table A and Table B will join based on A.ID =B.ID and A.Address=B.Address
And this result with join with Table C

Use OR and AND operator to simulate if condition in ON clause. Try this Join
SELECT *
FROM A
INNER JOIN B
ON ( A.name = 'A'
AND A.ID = B.ID )
OR ( A.Name = 'B'
AND A.ID = B.ID
AND A.Address = B.Address )
INNER JOIN C
ON B.school = C.school

You can try below code :
SELECT *
FROM A
INNER JOIN B
ON ( (B.Name = 'A' AND A.ID = B.ID)
OR (B.Name = 'B' AND A.ID = B.ID AND A.Address=B.Address)
)
You can now join the result with table C
Thank You

assuming there A.Name is either A or B:
SELECT *
FROM A
JOIN B ON ( A.ID = B.ID )
AND ( A.Name = 'A' OR A.Address = B.Address )
JOIN C ON B.school = C.school

SELECT * FROM A INNER JOIN B
ON A.ID = B.ID
INNER JOIN C
ON B.SCHOOL = C.SCHOOL
WHERE A.NAME = 'A'
UNION ALL
SELECT * FROM A INNER JOIN B
ON A.ID =B.ID and A.Address=B.Address
INNER JOIN C
ON B.SCHOOL = C.SCHOOL
WHERE A.NAME = 'B'
This might work

Related

SQL multi-part identifier can't be bound in SELECT

Is it possible to add a case using a column from other tables than first in the from section?
I can't use anything like C.code or Y.anything in the SELECT part:
SELECT
fromTableA, fromTableA, fromTableA,
CASE
WHEN fromTableA = anyValue THEN 'is_ok'
WHEN B.fromTableB = anyValue THEN 'couldnt.be.bound'
WHEN fromTableB = anyValue THEN 'invalid.column.name'
END AS X
FROM
(SELECT fromTableA,
SUM(fromTableA),
CASE WHEN A.fromTableA = 'anything' THEN 'still ok'
WHEN C.fromTableC = 'allowed' THEN 'no problem'
FROM tableA A
JOIN tableB B ON A.id = B.id
JOIN tableC C ON C.id = B.id
Having SUM(fromTableA) > 0
) AS Y
Edit: What I need is to use columns from table B or C in the outer Select ( I just can't remove the inner select because i would lost cases and aggregation operations there are in the inner select).
The following should be all you need, a derived table here doesn't accomplish anything.
select A.Cols...,
case
when A.col1 = anyValue then 'is_ok'
when B.Col1 = anyValue then 'couldnt.be.bound'
when B.Col2 = anyValue then 'invalid.column.name'
end as X
from tableA A
join tableB B on A.id = B.id
join tableC C on C.id = B.id;

performance significantly reduced when inner join table and views

I have three views in my sql server:
CREATE VIEW [dbo].[v_CompanyLabelCreate]
AS
SELECT
c.Id AS Id,
c.[Name] AS CompanyName,
CASE WHEN r.ApprovedPatentCreativeApplication > 2 OR r.ApprovedCopyRightBookApplication + r.ApprovedCopyRightSoftwareApplication > 4 OR NumberInProduction + NumberNotInProduction > 10 THEN N'创造型'
ELSE NULL END AS Label
FROM Company c INNER JOIN ResearchInfo r ON c.Id = r.CompanyID
WHERE c.Submitted = 1
CREATE VIEW [dbo].[v_CompanyLabelHighPotential]
AS
SELECT
c.Id AS Id,
c.[Name] AS CompanyName,
CASE WHEN si1.Income >= 1000000 AND si2.Income <> 0 AND ((si1.Income -si2.Income)/si2.Income) >= 1 THEN N'潜力型'
WHEN n1.TotalProfit >= 500000 AND n2.TotalProfit <> 0 AND ((n1.TotalProfit - n2.TotalProfit)/n2.TotalProfit) >= 1 THEN N'潜力型'
WHEN nfa1.AssetsTotal >= 5000000 AND nfa2.AssetsTotal <> 0 AND ((nfa1.AssetsTotal - nfa2.AssetsTotal)/nfa2.AssetsTotal) >= 1 THEN N'潜力型'
ELSE NULL END AS Label
FROM Company c INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2
INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1
INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2
INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1
INNER JOIN NonFloatingAsset nfa1 ON c.Id = nfa1.CompanyID AND nfa1.YearQuarterID = 2
INNER JOIN NonFloatingAsset nfa2 ON c.Id = nfa2.CompanyID AND nfa2.YearQuarterID = 1
WHERE c.Submitted = 1
CREATE VIEW [dbo].[v_CompanyLabelHighTotalPolicies]
AS
SELECT
c.Id AS Id,
c.[Name] AS CompanyName,
CASE WHEN p.NumberOfPolicies >= 4 AND cp.PolicyID IS NOT NULL THEN N'政策大户'
ELSE NULL END AS Label
FROM Company c LEFT JOIN (SELECT CompanyID, COUNT(*) AS NumberOfPolicies FROM CompanyPolicy GROUP BY CompanyID) p ON c.Id = p.CompanyID
LEFT JOIN (SELECT CompanyID, PolicyID FROM CompanyPolicy WHERE PolicyID = 7) cp ON c.Id = cp.CompanyID
WHERE c.Submitted = 1
When I run a select query which inner joins these three views:
select *
from v_CompanyLabelCreate clc
INNER JOIN v_CompanyLabelHighPotential clhp ON clc.Id = clhp.Id
INNER JOIN v_CompanyLabelHighTotalPolicies chtp ON clc.Id = chtp.Id
It is fast and smooth. However, when I try to run a select query which inner join these three views with some other tables:
select *
FROM Company c
INNER JOIN BasicInfo b ON c.Id = b.CompanyID
INNER JOIN CompanyDimension cd ON c.Id = cd.CompanyID
INNER JOIN TotalProfit t ON c.Id = t.CompanyID AND t.YearQuarterID = 2
INNER JOIN SaleCost sc ON c.Id = sc.CompanyID AND sc.YearQuarterID = 2
INNER JOIN CompanyFinancialIndex cfi ON c.Id = cfi.CompanyID AND cfi.YearQuarterID = 6
INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2
INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1
INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2
INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1
INNER JOIN v_CompanyLabelCreate clc ON c.Id = clc.Id
INNER JOIN v_CompanyLabelHighPotential clhp ON clc.Id = clhp.Id
INNER JOIN v_CompanyLabelHighTotalPolicies chtp ON clc.Id = chtp.Id
WHERE c.Submitted = 1
It looks like it will take forever to get the result (Download the execution plan here: the execution plan). Now, if I just run the query without inner joining the three views like this:
select *
FROM Company c
INNER JOIN BasicInfo b ON c.Id = b.CompanyID
INNER JOIN CompanyDimension cd ON c.Id = cd.CompanyID
INNER JOIN TotalProfit t ON c.Id = t.CompanyID AND t.YearQuarterID = 2
INNER JOIN SaleCost sc ON c.Id = sc.CompanyID AND sc.YearQuarterID = 2
INNER JOIN CompanyFinancialIndex cfi ON c.Id = cfi.CompanyID AND cfi.YearQuarterID = 6
INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2
INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1
INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2
INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1
WHERE c.Submitted = 1
It is fast and smooth again.
About the tables used:
Company: A table which stores company Ids and company names. Of course c.Id is the PK and it will be referred to as Company ID later.
ResearchInfo, BasicInfo, CompanyDimension, CompanyFinancialIndex: CompanyID is foreign key, every company only has at most one row in this table.
SaleIncome, SaleCost, NetProfit, NonFloatingAsset, TotalProfit: the combination of CompanyID and YearQuarterID work as Primary Key, although every table has an identity field which is defined as the PK.
You also can have a missed index issue, but your query is a bit complex. You can try to reduce the complexity using cte table like (You need the field names be unique in CTEs):
WITH cte_tb1
AS (SELECT * -- UNIQUE NAMES FIELDS IS REQUIRED
FROM company c
INNER JOIN basicinfo b
ON c.id = b.companyid
INNER JOIN companydimension cd
ON c.id = cd.companyid
INNER JOIN totalprofit t
ON c.id = t.companyid
AND t.yearquarterid = 2
INNER JOIN salecost sc
ON c.id = sc.companyid
AND sc.yearquarterid = 2
INNER JOIN companyfinancialindex cfi
ON c.id = cfi.companyid
AND cfi.yearquarterid = 6
INNER JOIN saleincome si1
ON c.id = si1.companyid
AND si1.yearquarterid = 2
INNER JOIN saleincome si2
ON c.id = si2.companyid
AND si2.yearquarterid = 1
INNER JOIN netprofit n1
ON c.id = n1.companyid
AND n1.yearquarterid = 2
INNER JOIN netprofit n2
ON c.id = n2.companyid
AND n2.yearquarterid = 1
WHERE c.submitted = 1),
cte_tb2
AS (SELECT * -- UNIQUE NAMES FIELDS IS REQUIRED
FROM v_companylabelcreate clc
INNER JOIN v_companylabelhighpotential clhp
ON clc.id = clhp.id
INNER JOIN v_companylabelhightotalpolicies chtp
ON clc.id = chtp.id)
SELECT *
FROM cte_tb1 a
INNER JOIN cte_tb2 b
ON a.id = b.id

Joining condition showing inappropriate result

SELECT a.name,
nvl(c.bill_amount,0),
b.status
FROM table_1 a left outer join table_2 b
ON a.name = b.name and
b.status = 'YES'
left outer join table_3 c on B.phone_number = C.phone_number
AND B.email = C.email
where
a.VALID = 'Y';
I wrote this query recently, the condition b.status = 'yes' is not fulfilled in the above query and status shows NULL value in it. I want to refine my records according to this condition b.status ='yes'.
Try the following:
SELECT a.name, nvl(c.bill_amount,0), b.status
FROM table_1 a left outer join table_2 b
ON a.name = b.name
left outer join table_3 c on b.phone_number = c.phone_number
where
a.VALID = 'Y' and
b.status = 'YES' and
b.email = c.email

TSQL: SUM not working like i thought it would

I have the following query:
SELECT
a.Name,
ISNULL(CAST(sum((b.qty * b.unit_rate)* b.Eng_RPQ )/100 AS DECIMAL(8,1)),0) AS [EngHours],
SUM(BR.BlendedRate)
FROM
Activity_Details b
INNER JOIN
Activity c on b.activity_id = c.id
INNER JOIN
Project p on p.id = c.project_id
RIGHT OUTER JOIN
Discipline a on c.discipline_id = a.id
INNER JOIN
(SELECT
a.Name, c.id,
CAST(f.POH * (d.HourlyRate * (1-(r.Discount/100))/100) AS DECIMAL(8,2)) AS BlendedRate
FROM
Activity_Details b
INNER JOIN
Activity c on b.activity_id = c.id
INNER JOIN
Team f on f.activity_id = c.id
INNER JOIN
SOF_Details d on d.id = f.sof_detail_id
INNER JOIN
Project p on p.id = c.project_id
INNER JOIN
Rate r on r.projectid = p.id
INNER JOIN
Teammate_Type tt on tt.id = f.team_type_id
RIGHT OUTER JOIN
Discipline a on c.discipline_id = a.id
GROUP BY
a.Name, c.id, f.POH, d.HourlyRate, r.Discount) AS BR ON BR.id = c.id
GROUP BY
a.Name
ORDER BY
a.Name
Which yields:
Name EngHours BlendedRate
Architechtural 80.8 38.48
Architechtural 80.8 55.33
Architechtural 80.8 55.40
I want to SUM this BlendedRate and ROUND it but if i try SUM(BR.BlendedRate) to the SELECT and remove the BR.BlendedRate in the GROUP BY
I get:
Name EngHours BlendedRate
Architechtural 242.3 895.26
I was expecting BlendedRate to equal 149.21
Any idea what i am doing wrong?
unable to comment due to reputation. It is a crude solution, but your code is returning duplicated (seemingly 6) records. The code should be fixed elsewhere, but without sample data it is difficult. In the mean time a crude solution would be to add a distinct clause to the sum function
SUM( DISTINCT BR.BlendedRate)

If statement within an inner join

Is there a way to have an if statement determine whether a join is necessary or not?
I need this because there are multiple foreign keys in the data I querying. if any of the foreign keys are null I need to change the SQL statement. I would like to write one statement that can be aware of any null values.
This is what I would like to do...
select a.*,b.* from table1 a inner join table2 b on a.id = b.id
if a.InspectorID is not null
{inner join table3 c on a.InspectionID = c.id}
else do nothing...
try this out...
select a.*,b.* from table1 a inner join table2 b on a.id = b.id
left join table3 c on a.InspectionID = c.id
where a.InspectorID is null or a.InspectionID = c.id
I am not sure, if you can conditionally join tables, but the "if" statement in t-sql is calles
case.
What about using union
select a.*,b.*
from table1 a
inner join table2 b on a.id = b.id
inner join table3 c on a.InspectionID = c.id
union all
select a.*,b.*
from table1 a
inner join table2 b on a.id = b.id
where a.InspectionID is null
If I understand correctly, you could use:
select a.*,b.*,c.fields
from table1 a inner join table2 b on a.id = b.id
left join table3 c on a.InspectionID = c.id
where a.InspectionID IS NOT NULL
Use dynamic sql. For detail about dynamic sql go through:
http://exacthelp.blogspot.in/2013/02/writing-dynamic-sql-queries-in-sql.html

Resources