How to replace an OR statement from a join in sql server - sql

I have the following query that uses an or statement on a join, so basically if one condition on the join isn't met it must check the next condition. The problem is that with the OR statement it takes really long to run but when I remove one of the OR conditions it runs instantly. is there a better way to do this with both conditions without using the OR statement so it would speed up the query
select t5.TransactionNumber
,t4.ID
,t3.[Entry] AS Amount
,t2.Address AS AddressDetail
,t1.PhoneNumber AS ContactNumber
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK) ON t2.FicaID = t1.FicaId
inner join Table3 t3 (NOLOCK) ON (t3.ID = t2.ID AND t3.Code = t2.Code) or (t3.TypeID = t2.TypeID) //on this join i have an or statement if one condition isnt met it must check the next condition
LEFT JOIN Table4 t4 (NOLOCK) ON t4.Result = t3.Result
LEFT JOIN Table5 t5 (NOLOCK) ON t5.AccNum = t3.AccNum
where t1.date>'2018-09-01' and t1.date<'2018-09-30'

By the rule of distributivity in logic,
P OR (Q AND R) can be written as
(P OR Q) AND (P OR R).. maybe that helps?

You could try by using left join and COALESCE function
select t5.TransactionNumber
,t4.ID
,COALESCE(t3.[Entry],t33.[Entry]) AS Amount
,t2.Address AS AddressDetail
,t1.PhoneNumber AS ContactNumber
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK) ON t2.FicaID = t1.FicaId
left join Table3 t3 (NOLOCK) ON (t3.ID = t2.ID AND t3.Code = t2.Code)
left join Table3 t33 (t33.TypeID = t2.TypeID) //I moved it to left join
LEFT JOIN Table4 t4 (NOLOCK) ON t4.Result = t3.Result
LEFT JOIN Table5 t5 (NOLOCK) ON t5.AccNum = t3.AccNum
where t1.date>'2018-09-01' and t1.date<'2018-09-30'

You can try below query :
select * from
(
select t5.TransactionNumber
,t4.ID
,t3.[Entry] AS Amount
,t2.Address AS AddressDetail
,t1.PhoneNumber AS ContactNumber
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK) ON t2.FicaID = t1.FicaId
inner join Table3 t3 (NOLOCK) ON (t3.ID = t2.ID AND t3.Code = t2.Code)
)A
join Table3 t3 (NOLOCK) ON (A.TypeID = t3.TypeID)
LEFT JOIN Table4 t4 (NOLOCK) ON t4.Result = t3.Result
LEFT JOIN Table5 t5 (NOLOCK) ON t5.AccNum = t3.AccNum
where t1.date>'2018-09-01' and t1.date<'2018-09-30'

Related

multiple inner joins in bigquery result in duplicated rows

Im tryin to join 6 tables in bigquery named
T0, T1, T2, T3, T4, T5
The tables result im interested are T0 and T1
after query this tables I got 43 matches
SELECT
T1.F1,
T0.F2,
T0.F3,
T0.F4,
T1.F5,
T1.F6,
T1.F7,
T1.F8
T0.F9
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 on T1.F1= T0.F1
WHERE T0.F1 = "010001476713"
AND T0.F2 = T1.F2
ORDER BY T0.F4
But when I run this with multiple INNER JOIN I got 800 results not the 43, results are duplicated
SELECT
T2.F11,
T3.F15,
T2.F12,
T3.F16,
T3.F17,
T1.F1,
T2.F13,
T3.F17,
T5.F18,
T5.F19,
T5.F20,
T2.F14,
T0.F9,
T1.F10,
T4.F3,
T4.F21,
T4.F22,
T0.F2,
T3.F23,
T0.F3,
T0.F4,
T1.F5,
T1.F6,
T1.F7,
T1.F8
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 ON T1.F1= T0.F1
INNER JOIN `TABLE3` T3 ON T3.F1=T1.F1
INNER JOIN `TABLE2` T2 ON T2.F24 = T3.F24
INNER JOIN `TABLE4` T4 ON T4.F3 = T0.F3
INNER JOIN `TABLE5` as T5 ON T5.F1=T0.F1
WHERE T0.F1 = "010001476713"
AND T0.F2 = T1.F2
ORDER BY T0.F4
When I get duplicate rows, I solve it like this:
You get 43 results on your inner join of table T0 & T1. So far so good.
Now comment out everything related to table T2, T4, & T5 (I've placed the commas at the beginning of the row for easier commenting out) like this
SELECT
--T2.F11,
T3.F15
--,T2.F12
,T3.F16
,T3.F17
,T1.F1
--,T2.F13
,T3.F17
--,T5.F18
--,T5.F19
--,T5.F20
--,T2.F14
,T0.F9
,T1.F10
--,T4.F3
--,T4.F21
--,T4.F22
,T0.F2
,T3.F23
,T0.F3
,T0.F4
,T1.F5
,T1.F6
,T1.F7
,T1.F8
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 ON T1.F1= T0.F1 and T0.F2 = T1.F2
INNER JOIN `TABLE3` T3 ON T3.F1=T1.F1
--INNER JOIN `TABLE2` T2 ON T2.F24 = T3.F24
--INNER JOIN `TABLE4` T4 ON T4.F3 = T0.F3
--INNER JOIN `TABLE5` as T5 ON T5.F1=T0.F1
WHERE T0.F1 = "010001476713"
ORDER BY T0.F4
I've moved the and T0.F2 = T1.F2 from the where to on in the inner join. When you run this query, do you still get 43 rows, or more? If more, you need to figure out what it is double matching on, and add that to your on statement of it really is a 1-1 relationship, or perhaps group the results if you don't want multiple matches. You may need to comment out your select statement and select all to really figure it out, like this:
SELECT *
/*
--T2.F11,
T3.F15
--,T2.F12
,T3.F16
,T3.F17
,T1.F1
--,T2.F13
,T3.F17
--,T5.F18
--,T5.F19
--,T5.F20
--,T2.F14
,T0.F9
,T1.F10
--,T4.F3
--,T4.F21
--,T4.F22
,T0.F2
,T3.F23
,T0.F3
,T0.F4
,T1.F5
,T1.F6
,T1.F7
,T1.F8
*/
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 ON T1.F1= T0.F1 and T0.F2 = T1.F2
INNER JOIN `TABLE3` T3 ON T3.F1=T1.F1
--INNER JOIN `TABLE2` T2 ON T2.F24 = T3.F24
--INNER JOIN `TABLE4` T4 ON T4.F3 = T0.F3
--INNER JOIN `TABLE5` as T5 ON T5.F1=T0.F1
WHERE T0.F1 = "010001476713"
ORDER BY T0.F4
Once you figure out what rows are causing the duplication, you either group the results or add an 'and' statement to the on clause to make it a 1-1, and then move on. You then uncomment the parts of the query related to T2 and do the same thing, then T4 and then T5. If you send me the results of the query above, I can help you figure out what your on clause needs to be to keep it from duplicating.
thank you #jenstretman, I find table 4 to be duplicating matches by using a foreign Key with non-primary Key creating duplicates, the solution was to use a DISTINCT to only select specifically matched rows.
SELECT DISTINCT
T2.F11,
T3.F15,
T2.F12,
T3.F16,
T3.F17,
T1.F1,
T2.F13,
T3.F17,
T5.F18,
T5.F19,
T5.F20,
T2.F14,
T0.F9,
T1.F10,
T4.F3,
T4.F21,
T4.F22,
T0.F2,
T3.F23,
T0.F3,
T0.F4,
T1.F5,
T1.F6,
T1.F7,
T1.F8
FROM `TABLE0` T0
INNER JOIN `TABLE1` T1 ON T1.F1= T0.F1
INNER JOIN `TABLE3` T3 ON T3.F1=T1.F1
INNER JOIN `TABLE2` T2 ON T2.F24 = T3.F24
INNER JOIN (SELECT DISTINCT T4.F3, T4.F21, T4.F22, FROM `TABLE4` T4)T4 ON T4.F3 = T0.F3
INNER JOIN `TABLE5` as T5 ON T5.F1=T0.F1
WHERE T0.F1 = "010001476713"
AND T0.F2 = T1.F2
ORDER BY T0.F4

Joining tbl1 to select statement twice with join to tbl2 that also joins to tbl3

I'm using SQL server manger.
I have 3 tables
I need a query that pulls t1 ands add an Origin Basin and a Destination Basin.
So far I have the following:
select T1.[Country (destination)], T3.AreaName
From T1
left outer join T2 on
T1.[Country (destination)] = T2.CountryName
inner join T3 on
T2.AreaID = T3.AreaID
inner join T3 on
T2.AreaID = T3.AreaID
Which returns:
Country | Area
However, I'm having trouble doing this for the second country column. I believe you use aliases. I've tried:
select (select AreaName
FROM T3
where T3.AreaID = T2.AreaID) as 'Area Imp',
(select AreaID
From T2
where T2.CountryName = T1.[Country (origin)]) as 'x',
(select AreaID
From T2
where T2.CountryName = T1.[Country (destination)]) as 'y'
FROM T1
But I can't get it to work.
This is what you need to do:
select t1.date, t1.country_destination, t1.country_origin, destination_area.AreaName as area_destination, origin_area.AreaName as area_origin
from t1 as t1 join t2 as destination on t1.country_destination = destination.countryname
join t2 as origin on t1.country_origin = origin.countryname
join t3 as destination_area on t2.areaid = destination_area.areaid
join t3 as origin_area on t2.areaid = origin_area.areaid
You will need to join with the same table twice, both for t2 and t3 so that you get the matching records for your needs.
It helps usually to put aliases that match the purpose of the join (in this case, destination and origin) when writing the query.
I think what you're trying to do is something like this:
select T1.*, T3dest.AreaName, T3orig.AreaName
From
T1
inner join
T2 T2dest on
T1.[Country (destination)] = T2dest.CountryName
inner join
T3 T3dest on
T2dest.AreaID = T3dest.AreaID
inner join
T2 T2orig on
T1.[Country (origin)] = T2orig.CountryName
inner join
T3 T3orig on
T2orig.AreaID = T3orig.AreaID
Note that I've switched to inner joins throughout, at the moment. If you do want left join semantics, you either need to use those for all of the joins to the T2 and T3 tables or you need to change the join order (so that the relevant T3 joins to the T2 tables occur before the attempted join with T1). It's not clear from the sample data if that's required, however.
Try this, You would still want to join on area id's
select T1.Date,T1.[Country (destination)], null [Country (origin)], T3.AreaName [AreaName(Destination)], null [AreaName(Origin)]
From T1
left outer join T2 on
T1.[Country (destination)] = T2.CountryName
inner join T3 on
T2.AreaID = T3.AreaID
union all
select T1.Date,null [Country (destination)], t1.[Country (origin)], Null [AreaName(Destination)], t3. [AreaName(Origin)]
From T1
left outer join T2 on
T1.[Country (Origin)] = T2.CountryName
inner join T3 on
T2.AreaID = T3.AreaID

Joining multiple tables by skipping On condition for few tables and join them alone

I want to understand how we can join by skipping the On condition. Let me explain with example. If you notice in below query, there is no ON condition for T3 and I am just joining with that table to T4 table.
Question: How Data set will create and how that will combine to other other data set?
SELECT * FROM T1
INNER JOIN T2 ON T1.ID = T2.ID
INNER JOIN T3
LEFT JOIN T4 ON T3.ID = T4.ID
LEFT JOIN T5 ON T1.ID = T5.ID
Well, when there is no join relation, then you are basically performing a CROSS JOIN , your query is basically equivalent to :
SELECT * FROM T1
INNER JOIN T2 ON T1.ID = T2.ID
CROSS JOIN(SELECT * FROM T3
LEFT JOIN T4 ON T3.ID = T4.ID)
LEFT JOIN T5 ON T1.ID = T5.ID

SQL Join multiple tables using where clause

I want to write a sql statement:
Select * FROM table1
inner join table2 AS t2
ON
inner join table3 AS t3
ON
inner join table4 AS t4
ON
Where FK_Client_ID = 4
All tables have the client ID in common. So Not sure what to do on the ON.
Will it be something like ON t2.FK_Client_ID = ...... not sure.
So I just want all the data from those tables that has FK_Client_ID in common.
Select *,
(Select FK_Client_ID from table2 where FK_Client_ID = t1.FK_Client_ID )As TID1,
(Select FK_Client_ID from table3 where FK_Client_ID = t1.FK_Client_ID )As TID2,
(Select FK_Client_ID from table4 where FK_Client_ID = t1.FK_Client_ID )As TID3
FROM table1 t1
Select * FROM table1 t1 inner join table2 t2
ON t1.FK_Client_ID = t2.FK_Client_ID
inner join table3 t3
ON t1.FK_Client_ID = t3.FK_Client_ID
inner join table4 t4
ON t1.FK_Client_ID = t4.FK_Client_ID
Where t1.FK_Client_ID = 4
Try this
Select * FROM table1 t1
inner join table2 AS t2
ON t2.FK_Client_ID = t1.FK_Client_ID
inner join table3 AS t3
ON t3.FK_Client_ID = t1.FK_Client_ID
inner join table4 AS t4
ON t4.FK_Client_ID = t1.FK_Client_ID
Where t1.FK_Client_ID = 4
if your foreign field name is "FK_Client_ID" and primary key in table1 is "Client_ID"
Select * FROM table1
inner join table2 AS t2
ON t2.FK_Client_ID = table1.Client_ID
inner join table3 AS t3
ON t3.FK_Client_ID = table1.Client_ID
inner join table4 AS t4
ON t4.FK_Client_ID = table1.Client_ID
Where table1.Client_ID = 4
Since you are using inner join no matter you join them with table1 or any other of them

SQL Server - use columns from the main query in the subquery

Is there any way to get a column in real time, from a main query, and use it in a subquery?
Something like this: (Use A.item in the subquery)
SELECT item1, *
FROM TableA A
INNER JOIN
(
select *
from TableB B
where A.item = B.item
) on A.x = B.x;
Ok, here is the real thing:
I need to modify this existing query. It worked before, but now that the database changed, I need to do some modifications, add some comparisons. As you can see there are a lot of JOINS, and one of them is a subquery. I need to add a comparison from a column from the main query (from the table T0 for example) to the subquery (like this: T6.UnionAll_Empresa = T0.UnionALl_Empresa)
Select T0.UnionAll_Empresa,<STUFF>
from [UNION_ALL_BASES]..OINV T0 with (nolock)
inner join [UNION_ALL_BASES]..INV6 T1 with (nolock) on t0.DocEntry = t1.DocEntry and t0.UnionAll_Empresa = t1.UnionAll_Empresa
inner join
(
select
t1.CompanyID,
T2.CompanyDb,
t1.OurNumber,
T6.BankCode,
T6.BankName,
T3.[Description] Situation,
T1.[Status],
T5.Descrption nomeStatus,
T1.Origin,
T1.DocEntry,
T1.DocType,
T1.ControlKey,
T1.CardCode,
T4.[Description] ContractBank,
T1.PayMethodCode,
T1.DueDate,
T1.DocDate,
T1.InstallmentID,
T1.InstallmentValue,
T1.Correction,
T1.InterestContractural,
T1.FineContract,
T1.ValueAbatment,
T1.ValueDiscount,
T1.ValueFineLate,
T1.ValueInterestDaysOfLate,
T1.OtherIncreases,
T1.ValueInWords,
T1.ValueDocument,
T1.DigitalLine,
T1.Document
from [IntegrationBank]..BillOfExchange T1 with (nolock)
inner join [InterCompany2]..CompanyHierarchy T2 with (nolock) on T1.CompanyID = T2.ID
left join [IntegrationBank]..BillOfExchangeSituation T3 with (nolock) on T1.Situation = T3.ID
inner join [IntegrationBank]..ContractBank T4 with (nolock) on T1.ContractBank = T4.ID
inner join [IntegrationBank]..BoeStatus T5 with (nolock) on T1.[Status] = T5.ID
inner join [UNION_ALL_BASES]..ODSC T6 with (nolock) on T4.BankKey = T6.AbsEntry and **T6.UnionAll_Empresa = T0.UnionALl_Empresa** --I need to do this
where T1.[Status] <> 5
and T2.CompanyDb = **T0.UnionAll_Empresa** --I need to do this
) TBI on (T1.DocEntry = TBI.DocEntry and T1.InstlmntID = TBI.InstallmentID and TBI.DocType = T1.ObjType )
inner join [UNION_ALL_BASES]..OCTG T2 on T0.GroupNum = T2.GroupNum and T0.UnionAll_Empresa = T2.UnionAll_Empresa
inner join [UNION_ALL_BASES]..OSLP T3 on T0.SlpCode = T3.SlpCode and T0.UnionAll_Empresa = T3.UnionAll_Empresa
where not exists (select 1
from [UNION_ALL_BASES]..RIN1 A with (nolock)
inner join [UNION_ALL_BASES]..ORIN B with (nolock) on A.DocEntry = B.DocEntry and A.UnionAll_Empresa = B.UnionAll_Empresa
where A.BaseEntry = T0.DocEntry
and B.SeqCode = ''1'' )
You can user OUTER APPLY
SELECT *
FROM tbl1
OUTER APPLY ( SELECT TOP 1
currency_id,
SUM(taxrate) AS taxrate
FROM tbl2
WHERE wuptr.currency_id = tbl1.currency_id
GROUP BY tbl2.currencyid
)
You don't need a subquery for that:
SELECT item1, *
FROM TableA A
INNER JOIN
TableB B
ON A.item = B.item
AND A.x = B.x;
I can't think of a scenario where you would need to JOIN on a subquery with a filter like that where it wouldn't be equivalent to just reference the field directly in the outer query.
You can reference the outer table in the subquery in the WHERE clause, though:
SELECT <stuff>
FROM Table t
WHERE EXISTS (SELECT 1 from TableB B
WHERE t.id = b.id)
EDIT
For your actual code, just change the JOIN criteria to this:
) TBI on (T1.DocEntry = TBI.DocEntry
and T1.InstlmntID = TBI.InstallmentID
and TBI.DocType = T1.ObjType
AND TBI.CompanyDB = T0.UnionAll_Empresa )
If you want to join on to a subquery and "get a column in real-time"/ reference a column from the main query, then there is a trick to doing this.
You can't access the tables which are outside of the subquery if it's used as an aliased table, in other words, this SQL can never access A:
...
INNER JOIN
(
select *
from TableB B
where A.item = B.item
) on A.x = B.x;
The way to access A would be like this:
SELECT item1, *
FROM TableA A
INNER JOIN TableB on TableB.item = TableA.item and TableB.item in
(
select top 1 B.Item
from TableB B
where A.item = B.item
)
Just ignore the "top 1" piece, I just added that to show that there may a reason for doing a join like this.
So, basically if you want to reference an item from the query in the subquery, just move the subquery to the ON section of a join and use the IN keyword as illustrated above.
You can do this by naming the tables of the main query and the nested query.
For example:
SELECT continent, name, population FROM world x
WHERE population >= ALL
(SELECT population FROM world y
WHERE y.continent=x.continent
AND population>0)
reference: http://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial
Not sure why people are over-complicating this. #JNK is correct that you can move the predicate into the main query. For completeness, I will demonstrate.
You have two predicates in your subquery that reference T0:
T6.UnionAll_Empresa = T0.UnionAll_Empresa
T2.CompanyDb = T0.UnionAll_Empresa
The first is an INNER JOIN predicate on the table T6, and the second a WHERE clause - these are both "hard" filters, and will filter out results that don't match (unlike a LEFT OUTER JOIN which will simply set reference to that table's values to NULL).
Well, since T6.UnionAll_Empresa and T2.CompanyDb both need to filter against T0.UnionAll_Empresa, then we can simply change the INNER JOIN predicate on T6 to this:
T2.CompanyDb = T6.UnionAll_Empresa
Then, we can remove the WHERE clause in the subquery, and we can add this JOIN predicate to TBI in the main query:
TBI.CompanyDb = T0.UnionAll_Empresa
...making the entire query this:
Select T0.UnionAll_Empresa,<STUFF>
from [UNION_ALL_BASES]..OINV T0 with (nolock)
inner join [UNION_ALL_BASES]..INV6 T1 with (nolock) on t0.DocEntry = t1.DocEntry and t0.UnionAll_Empresa = t1.UnionAll_Empresa
inner join
(
select
t1.CompanyID,
T2.CompanyDb,
t1.OurNumber,
T6.BankCode,
T6.BankName,
T3.[Description] Situation,
T1.[Status],
T5.Descrption nomeStatus,
T1.Origin,
T1.DocEntry,
T1.DocType,
T1.ControlKey,
T1.CardCode,
T4.[Description] ContractBank,
T1.PayMethodCode,
T1.DueDate,
T1.DocDate,
T1.InstallmentID,
T1.InstallmentValue,
T1.Correction,
T1.InterestContractural,
T1.FineContract,
T1.ValueAbatment,
T1.ValueDiscount,
T1.ValueFineLate,
T1.ValueInterestDaysOfLate,
T1.OtherIncreases,
T1.ValueInWords,
T1.ValueDocument,
T1.DigitalLine,
T1.Document
from [IntegrationBank]..BillOfExchange T1 with (nolock)
inner join [InterCompany2]..CompanyHierarchy T2 with (nolock) on T1.CompanyID = T2.ID
left join [IntegrationBank]..BillOfExchangeSituation T3 with (nolock) on T1.Situation = T3.ID
inner join [IntegrationBank]..ContractBank T4 with (nolock) on T1.ContractBank = T4.ID
inner join [IntegrationBank]..BoeStatus T5 with (nolock) on T1.[Status] = T5.ID
inner join [UNION_ALL_BASES]..ODSC T6 with (nolock) on T4.BankKey = T6.AbsEntry and T2.CompanyDb = T6.UnionAll_Empresa
where T1.[Status] <> 5
) TBI on (T1.DocEntry = TBI.DocEntry and T1.InstlmntID = TBI.InstallmentID and TBI.DocType = T1.ObjType and TBI.CompanyDb = T0.UnionAll_Empresa)
inner join [UNION_ALL_BASES]..OCTG T2 on T0.GroupNum = T2.GroupNum and T0.UnionAll_Empresa = T2.UnionAll_Empresa
inner join [UNION_ALL_BASES]..OSLP T3 on T0.SlpCode = T3.SlpCode and T0.UnionAll_Empresa = T3.UnionAll_Empresa
where not exists (
select 1
from [UNION_ALL_BASES]..RIN1 A with (nolock)
inner join [UNION_ALL_BASES]..ORIN B with (nolock) on A.DocEntry = B.DocEntry and A.UnionAll_Empresa = B.UnionAll_Empresa
where A.BaseEntry = T0.DocEntry
and B.SeqCode = ''1''
)
This is entirely equivalent to what you have, and removes any reference to T0 from your subquery.
You can also use WITH
http://msdn.microsoft.com/en-us/library/ms175972.aspx