Table_A: Table_B:
Column_A Column_A Value EmpId
A A 1 1
B B 2 1
C - - -
D - - -
I have 2 tables as you can show above. I want to get all the records of Table_A related to the EmpId
My Expected Result related to EmpId - 1:
Column_A Value
A 1
B 2
C null
D null
I have used the below query:
Select * from Table_A a left join Table_B b on a.Column_A = b.Column_B
The above query will give my expected result but it as you can see it is not filtered on the basis of EmployeeId. Can anyone help me. Thanks
ANY QUICK HELP PLEASE
Select a.Column_A, b.Value
from Table_A a
left join Table_B b on a.Column_A = b.Column_B
and b.EmpID = 1
Should give you the expected results.
If you want to apply filters of EmpID, then just add where clause,
Select * from Table_A a
left join Table_B b on a.Column_A = b.Column_B
where b.EmpId = 1
Related
As an example I have a table in SQL Server :
Id
1
3
5
and I have a list of values 1,2,3
What is the query to select values of my list not in the table.
Expected result :
Id
2
Here are two approaches
Using Not Exists
Select *
from string_split('1,2,3',',') A
Where not exists ( select 1 from YourTable where ID=Value )
Using a LEFT JOIN
Select A.Value
from string_split('1,2,3',',') A
left Join YourTable B on A.value=B.ID
Where B.ID is null
Both Results are
Value
2
SELECT * FROM id_table WHERE id NOT IN (1,2,3);
I am trying to join 2 or more tables on MS SQL Server. All the tables have IsActive field which determines the active record. (IsActive = 1 means active record and IsActive = 0 means inactive record or record has been deleted from system)
So I have two conditions for joining the two or more tables.
On The first query,I filter the IsActive on the join clause
select * from table_A a
inner join table_B b
on a.ID = b.ID and b.IsActive = 1
inner join table_C c
on b.ID = c.ID and c.IsActive = 1
where a.IsActive = 1
On The second query, I also can filter IsActive on the where Clause
select * from table_A a
inner join table_B b
on a.ID = b.ID
inner join table_C c
on b.ID = c.ID
where a.IsActive = 1 and b.IsActive = 1
and c.IsActive = 1
notes: The relation from table A to B is one to one but from table A to C is one to many and also all the table has clustered index on primary key ID and the ID is auto increment.
So which one do you think is better? (assume each table has approximately 100.000 records (80% active records and 20% inactive records))
Thanks
The difference is simple but takes a careful eye to spot.
Consider the following example:
create table tbl_client as
select 1 as client_id, 'aaa' as client_name, 'Y' is_active from dual
union all
select 2, 'bbbbb', 'N' from dual
union all
select 3, 'cc', 'Y' from dual;
create table tbl_transaction as
select 1 transaction_id, 1 client_id, 123.34 amount from dual
union all
select 2, 1, 4353.45 from dual
union all
select 3, 2, 251.48 from dual;
Now, on these tables run the followoing queries:
Inner Join:
In an inner join, there is no difference in the results of the following two queries:
select c.client_name, t.amount, t.is_paid
from tbl_client c
inner join tbl_transaction t
on c.client_id = t.client_id
and t.is_paid = 'Y'; -- filter on join
select c.client_name, t.amount, t.is_paid
from tbl_client c
inner join tbl_transaction t
on c.client_id = t.client_id
where t.is_paid = 'Y'; -- filter in where
Both their result is the same as:
CLIENT_NAME AMOUNT IS_PAID
----------- ---------- -------
aaa 123.34 Y
aaa 4353.45 Y
Left Outer Join
This is where the difference kicks in.
Consider the following query:
select c.client_name, t.amount, t.is_paid
from tbl_client c
left outer join tbl_transaction t
on c.client_id = t.client_id
and t.is_paid = 'Y'; -- << filter in join
Result:
CLIENT_NAME AMOUNT IS_PAID
----------- ---------- -------
aaa 123.34 Y
aaa 4353.45 Y
cc -- << Note that client cc's transaction record is not there
bbbbb -- << and this client also shows up
And when you apply filter on where in a left outer join:
select c.client_name, t.amount, t.is_paid
from tbl_client c
left outer join tbl_transaction t
on c.client_id = t.client_id
where t.is_paid = 'Y'; -- << filter in where
Result:
CLIENT_NAME AMOUNT IS_PAID
----------- ---------- -------
aaa 123.34 Y
aaa 4353.45 Y -- No row for bbbbb or cc clients, just like the inner join
Summary
In short, when you put a filter on the joining condition, the filter is applied to the table being joined. For example, in the first case in the left outer join section, the row for tbl_transaction didn't show up for the client bbbbb.
But when you put a filter in the where clause, it filters the entire data set that is retrieved after joining all the tables (logically. Internal technical operations differ across RDBMSes). This is why the rows for bbbbb and cc didn't show up in the last query.
Fiddle
EDIT
As #DanGuzmanSqlServerMvp has mentioned in his comment, for the example you have posted in your question, the SQL Server query optimizer should execute the same plan. However, if there was an outer join in your query, the plans would be different.
I have two tables with identical definition.
T1:
Name VARCHAR(50)
Qty INT
T2:
Name VARCHAR(50)
Qty INT
This is the data each table has:
T1:
Name Qty
a 1
b 2
c 3
d 4
T2:
Name Qty
a 1
b 3
e 5
f 10
I want to have result which can sum the Qty from both the tables based on Name.
Expected resultset:
Name TotalQty
a 2
b 5
c 3
d 4
e 5
f 10
If am do Left Join or Right Join, it is not going to return me the Name from either of the tables.
What i am thinking is to create a temp table and add these records and just do a SUM aggregate on Qty column but i think there should be a better way to do this.
This is how my query looks like which does not return the expected resultset:
SELECT t1.Name, ISNULL(SUM(t1.Qty + t2.Qty),0) TotalQty
FROM t1
LEFT JOIN t2
ON t1.Name = T2.Name
GROUP BY t1.Name
Can someone please tell me if creating a temp table is OK here or there is a better way to do this?
You can use a full outer join:
SELECT
ISNULL(t1.Name, t2.Name) AS Name,
ISNULL(t1.Qty, 0) + ISNULL(t2.Qty, 0) AS TotalQty
FROM t1
FULL JOIN t2 ON t1.Name = T2.Name
See it working online: sqlfiddle
You can use a UNION ALL to select both tables as one, since they have the same definition. From there, you can nest them as a derived table, and then SUM on that:
SELECT [Name], SUM(Qty) AS TotalQty
FROM (
SELECT [Name], Qty
FROM t1
UNION ALL
SELECT [Name], Qty
FROM t2
) YourDerivedTable
GROUP BY [Name]
Table_A
TxID RelatedTxID
-------------------
1 NULL
2 NULL
3 1
Table_B
OrderID TxID OrderDescription
-----------------------------------
1 1 Description_1
2 2 Description_2
I want to get an output which will give me order description for the transaction. But if the transaction does not have an order description I want to display it's related transaction's order description (Related transaction will always have an order description)
Output
TxID RelatedTxID OrderDescription
------------------------------------
1 NULL Description_1
2 NULL Description_2
3 1 Description_1
I am thinking of something like below but stuck at what should come in the ISNULL expression.
select
a.TxID,
a.RelatedTxID,
ISNULL(b.OrderDescription, <<get its related transaction's order description>>)
from Table_A a
left outer join Table_B b
on a.TxID = b.TxID
Thanks
select
a.TxID,
a.RelatedTxID,
ISNULL(b1.OrderDescription, b2.OrderDescription)
from Table_A a
left outer join Table_B b1 on a.TxID = b1.TxID
left outer join Table_B b2 on a.RelatedTxID = b2.TxID
This should be simple enough, but somehow my brain stopped working.
I have two related tables:
Table 1:
ID (PK), Value1
Table 2:
BatchID, Table1ID (FK to Table 1 ID), Value2
Example data:
Table 1:
ID Value1
1 A
2 B
Table 2:
BatchID Table1ID Value2
1 1 100
2 1 101
3 1 102
1 2 200
2 2 201
Now, for each record in Table 1, I'd like to do a matching record on Table 2, but only the most recent one (batch ID is sequential). Result for the above example would be:
Table1.ID Table1.Value1 Table2.Value2
1 A 102
2 B 201
The problem is simple, how to limit join result with Table2. There were similar questions on SO, but can't find anything like mine. Here's one on MySQL that looks similar:
LIMITing an SQL JOIN
I'm open to any approach, although speed is still the main priority since it will be a big dataset.
WITH Latest AS (
SELECT Table1ID
,MAX(BatchID) AS BatchID
FROM Table2
GROUP BY Table1ID
)
SELECT *
FROM Table1
INNER JOIN Latest
ON Latest.Table1ID = Table1.ID
INNER JOIN Table2
ON Table2.BatchID = Latest.BatchID
SELECT id, value1, value2
FROM (
SELECT t1.id, t2.value1, t2.value2, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.BatchID DESC) AS rn
FROM table1 t1
JOIN table2 t2
ON t2.table1id = t1.id
) q
WHERE rn = 1
Try
select t1.*,t2.Value2
from(
select Table1ID,max(Value2) as Value2
from [Table 2]
group by Table1ID) t2
join [Table 1] t1 on t2.Table1ID = t1.id
Either GROUP BY or WHERE clause that filters on the most recent:
SELECT * FROM Table1 a
INNER JOIN Table2 b ON (a.id = b.Table1ID)
WHERE NOT EXISTS(
SELECT 1 FROM Table2 c WHERE c.Table1ID = a.id AND c.BatchID > b. BatchID
)