SQL - FILTER condition in JOIN clause - sql

I am inserting data to an already existing TableA and the following query is a part of a stored procedure. This part of the query inserts values into some columns of TableA. The stored procedure is very lengthy which has several insert statements to fill out the different columns in TableA.
INSERT INTO TableA (ID, Event, Date, Amount, Status_, Country)
(SELECT DISTINCT ID, Event, Date, Amount, c.Status, b.Country
FROM TableA1 a
JOIN TableB1 b ON b.employeeID = a.ID
JOIN TableC1 c ON c.Status = ‘Active’)
Usually, a join condition consists of two columns, for example (a.Status_ = c.Status). But here, it's replaced with a filter condition (JOIN TableC1 c ON c.Status = ‘Active’).
The select query alone executes well and returns results. I'm trying to understand the effect made by this filter condition.
Can you explain, please?
Thanks

It's the same as this...
SELECT DISTINCT
ID, Event, Date, Amount, c.Status, b.Country
FROM
(
TableA1 a
INNER JOIN
TableB1 b
ON b.employeeID = a.ID
)
CROSS JOIN
(
SELECT * FROM TableC1 WHERE Status = 'Active'
)
c
In effect, the INNER JOIN is resolved, and then each row from that is joined to every row from TableC1 WHERE Status = 'Active'
For example
TableA1
ID
Event
Date
Amount
1
e1
2022-01-01
11
2
e2
2022-02-02
22
TableB1
EmployeeID
Country
1
c1
2
c2
TableC1
some_id
Status
1
Sleeping
2
Active
3
Active
4
Sleeping
Would yield...
ID
Event
Date
Amount
Country
Status
(some_id, added by me)
1
e1
2022-01-01
11
c1
Active
2
1
e1
2022-01-01
11
c1
Active
3
2
e2
2022-02-02
22
c2
Active
2
2
e2
2022-02-02
22
c2
Active
3
You probably should have...
INNER JOIN
TableC1 c
ON c.some_id = b.some_other_id
AND c.Status = 'Active'

Related

SQL query doesnt return expected values

I have 3 tables. 1st table stores coil information, 2nd table store coil information in transport and 3rd stores reserved coils.
coils
ID
SERIAL
COLOR
MATERIAL
STATUS
1
12345
5
1
2
2
12346
4
1
3
3
12347
3
1
2
coils_in_transport
ID
SERIAL
COLOR
MATERIAL
STATUS
1
f34S5
5
1
2
2
A23GG6
4
1
3
3
ff2S147
3
1
2
reserved_coils
ID
NUMBER
QUANTITY
START
END
1
12345
25
2022-05-01
2023-05-01
3
12347
252
2022-01-01
2023-05-01
4
A23GG6
33
2022-04-01
2023-05-01
5
ff2S147
35
2022-08-01
2023-05-01
I need to write query that will get all reserved coils (reserved_coils) that has status 2 and for each coil I need to join tables for materials and colors
material
ID
NAME
1
color
ID
NAME
I wrote query but it doesn't show coils in transport that are reserved, here is what I tried
SELECT a.QUANTITY, a.START, a.END, b.name, m.name
FROM reserved_coils a
LEFT JOIN coils b ON a.number = b.serial
LEFT JOIN coils_in_transport c ON a.number = c.serial
LEFT JOIN material m ON b.material = m.id
LEFT JOIN material b ON b.material = b.id
where b.status = 2 and c.status = 2
To get all coils and colis_in_transport you need to use UNION for SELECT statements for both tables, each filtered by status value, which should be equal to 2. Then you need to do a JOIN between reserved_coils and the result of UNION to filter out reserved_coils rows.
Your query would be like this
SELECT
r.quantity,
r.start,
r.[end],
c.serial,
material.name AS material,
color.name AS color
FROM reserved_coils r
JOIN (
SELECT * FROM coils WHERE status = 2
UNION
SELECT * FROM coils_in_transport WHERE status = 2
) c ON r.number = c.serial
LEFT JOIN material ON material.id = c.material
LEFT JOIN color ON color.id = c.color
Demo
If you want left join twice on same table, this might help
SELECT a.QUANTITY, a.START, a.[END], isnull(b.serial,c.serial) serial,isnull(c1.name,c2.name) color, isnull(m.name,n.name) material
FROM reserved_coils a
LEFT JOIN coils b ON a.number = b.serial
LEFT JOIN coils_in_transport c ON a.number = c.serial
LEFT JOIN material m ON b.material = m.id
LEFT JOIN material n ON c.material = n.id
LEFT JOIN color c1 on b.color=c1.id
LEFT JOIN color c2 on c.color=c2.id
where isnull(b.status,c.status) = 2
DB<>Fiddle

Using Group By as part of a where clause

I'm trying to eliminate certain records from a dataset using SQL Server. The title of my post may be inaccurate, as a better solution may exist than what I have in mind.
In my query, I am selecting from Table A, and the rows that I want to end up with should meet the following criteria:
All rows where A.ItemNumber = B.ItemNumber
All rows where A.ItemNumber <> B.ItemNumber AND that row's Task value does not have another row that meets criteria #1.
So for the below example:
Gives us ItemNumber 102, 104, 106 rows.
Gives us ItemNumber 105 row.
100, 101 are removed from dataset because their Task (1) is associated with Table B at ItemNumber 102. Same for 103 with Task (2) being associated at ItemNumber 104.
Table A
Task ItemNumber
1 100
1 101
1 102
2 103
2 104
3 105
4 106
Table B
ItemNumber Data
102 aaa
104 bbb
106 ccc
My initial thought was to load Table A into a temp table, LEFT JOIN with Table B, and DELETE FROM {temp table} WHERE (data IS NULL AND {insert some kind of grouping logic here}). But I have been completely unable to figure out a grouping logic that will work for the problem. I spent the weekend hoping a solution would come to me, but am now giving in and seeking advice.
With a CTE that meets the 1st condition and UNION ALL to return the rest of the rows:
with cte as (
select a.*
from TableA a
where exists (select 1 from TableB where ItemNumber = a.ItemNumber)
)
select * from cte
union all
select a.* from TableA a
where not exists (select 1 from cte where Task = a.Task)
order by Task
See the demo.
Results:
Task ItemNumber
1 102
2 104
3 105
4 106
One way to phrase this puts all the filtering logic in the where clause:
select a.*
from tablea a
where exists (select 1
from tableb b
where b.itemnumber = a.itemnumber
) or
not exists (select 1
from tableb b2 join
tablea a2
on b2.itemnumber = a2.itemnumber
where a2.task = a.task
);
SELECT *
FROM TABLEA AS A
LEFT JOIN TABLEB AS B ON A.ItemNumber = B.ItemNumber
WHERE B.ItemNumber IS NOT NULL -- critera 1
OR (B.ItemNumber IS NULL AND B.ItemNumber NOT IN
(SELECT A.ItemNumber
FROM TABLEA AS A
JOIN TABLEB AS B ON A.ItemNumber = B.ItemNumber)) -- criteria 2

How to join only latest date values from another table and prevent duplication

I'm trying to lookup a unique value from table b and get it into table a.
Table b stores multiple values that are changing by date.
I would like to join but only getting the values with the latest date from table b.
Table a
Unique ID
1
2
Table b
Date Unique ID Price
01/01/2019 1 100
01/02/2019 1 101
01/03/2019 1 102
01/01/2019 2 90
01/02/2019 2 91
01/03/2019 2 92
Expected result
Unique ID Price Date
1 102 01/03/2019
2 92 01/03/2019
Appreciate your help!
Have a sub-query that returns each UniqueID together with its max date. IN that result.
select * from tablename
where (UniqueID, date) in (select UniqueID, max(date)
from tablename
group by UniqueID)
You want correlated subquery :
select b.*
from tableb b
where b.date = (select max(b1.date) from tableb b1 where b1.UniqueID = b.UniqueID);
If you want to go with JOIN then you can do JOIN with subquery :
select a.UniqueID , b.Price, b.Date
from tablea a inner join
tableb b
on b.UniqueID = a.UniqueID
where b.date = (select max(b1.date) from tableb b1 where b1.UniqueID = a.UniqueID);
A correlated subquery?
select b.*
from b
where b.date = (select max(b2.date) from b b2 where b2.unique_id = b.unique_id);

Join one row only over three tables

(My question has been asked a lot of times with two tables involved, and has been answered here, here and here. But I can't figure out how to do the same with three tables involved.)
I have three tables, A, B and C, where A has many B and B has many C. I want to join these tables and select zero or one rows per A, which one should be based on a condition in C.
Example, assume that:
SELECT
a.aId
,b.bId
,c.cId
FROM
a
INNER JOIN b ON b.aId=a.aId
INNER JOIN c ON c.bId=b.bId
WHERE
c.someColumn='foo'
...yields the following result:
aId bId cId
=== === ===
1 11 101
1 12 102
1 12 103
2 21 201
2 21 203
2 22 202
...then I would like to, for instance, retrieve two distinct A-rows, the ones with highest cId.
aId bId cId
=== === ===
1 12 103
2 21 203
You can use ROW_NUMBER:
WITH Cte AS (
SELECT
a.aId,
b.bId,
c.cId,
rn = ROW_NUMBER() OVER (PARTITION BY a.aId ORDER BY c.cId DESC)
FROM a
INNER JOIN b
ON b.aId = a.aId
INNER JOIN c
ON c.bId = b.bId
WHERE c.someColumn = 'foo'
)
SELECT
aId, bId, cId
FROM Cte
WHERE rn = 1

sql query for 3 tables

i have 3 tables (A,B,C)
Table A -
ID Name
1 Sam
2 Manuel
3 Jane
Table B
ID Tab_A_ID Name
1 1 Meer
2 1 Kutti
3 2 Mikaro
Table C
ID Tab_B_ID Price
1 1 255.11
2 1 30.52
3 3 125.22
I need a query that shall pick up the top price for TableA-Name from TableC. So only 1 top price for 1 nae record.
e.g.-
Sam - 255.11
Manuel - 125.22
How can i get this?
To get the max price per entry in A:
SELECT a.Name,
MAX(c.price)
FROM a
INNER JOIN b
ON a.id = b.tab_a_id
INNER JOIN c
ON b.id = c.tab_b_id
GROUP BY a.id, a.name
To get the max price per entry A per entry B:
SELECT a.Name,
b.Name
MAX(c.price)
FROM a
INNER JOIN b
ON a.id = b.tab_a_id
INNER JOIN c
ON b.id = c.tab_b_id
GROUP BY a.id, b.id, a.name, b.name
Note that entries in A without corresponding entires in B or entries in B without corresponding entries in C will not appear in the result. Use LEFT JOIN if you want to include these in the result.