Are there any differences between the results of these 2 queries? - sql

Update #A set Column1 = minC
from (select Ab.Column2, min(C.Column1) as minC
from #A Ab
inner join B on Ab.Column2 = B.Column2
inner join C on C.column2 = B.Column2 --No need to add again the A.col2 = B.col2
inner join D on D.column1 = B.column2
group by Ab.Column2) Grouped where Column2 = Grouped.Column2
and
Update #A set Column1 = minC
from (select Ab.Column2, min(C.Column1) as minC, B.column2 as tempcolumn
from #A Ab
inner join B on Ab.Column2 = B.Column2
inner join C on C.column2 = B.Column2 --No need to add again the A.col2=B.col2
group by Ab.Column2) Grouped
inner join D on D.column1 = Grouped.tempcolumn
where Column2 = Grouped.Column2
Are there any difference between the results of the 2 queries?

Related

Postgres how do I update all rows in a table with left join and case?

Assume that I have table A, and table B. Table B contains some rows from table A
How do I run an update like the following?
update table A
set A.column = case when B.id is present then B.column else null
from B where B.id = A.id OR B is null
EDIT
The original query is incomplete, this is the updated one i need help with
update table A
set A.column1 = case when B.id is present then B.column else null end,
set A.column2 = case when B.id is present then null else A.id end
from B
where B.id = A.id OR B is null
You can simply use a subquery:
UPDATE A SET A.column = (
SELECT B.column FROM B WHERE B.id = A.id
)
You can use a left join in the FROM clause as well to update multiple columns:
UPDATE A SET column1 = B.column1, column2 = B.column2
FROM A x LEFT JOIN B ON x.id = B.id
WHERE A.id = x.id
The table A in the FROM clause is only to allow a left join with B.

Equivalente to INNER

I want to structure a query with no using INNER JOIN. I figured out that an INNER like this:
Select A.Name
from A INNER JOIN B on (A.id1 = B.id1 AND A.id2 = B.id2)
Where B.id = #Id
produce the same as:
select A.Name
from A
where
A.id1 in (select B.id1 from B where B.id = #Id)
and
A.id2 in (select B.id2 from B where B.id = #Id)
Isn't it?
Note that my question is not about if it is better or not, only if it is an equivalent or if there is not an equivalente for that INNER.
Your second query may match id1 and id2 from different B rows, so that query may return rows not expected. You have to keep id1 and id2 together:
Use EXISTS:
select A.Name
from A
where exists (select * from B
where A.id1 = B.id1 AND A.id2 = B.id2
and B.id = #Id)
or "Row and table constructors"
select A.Name
from A
where (A.id1, A.id2) in (select B.id1, B.id2 from B where B.id = #Id)

How does Inner join 3 or more tables works?

I saw some questions about the subject, but frankly i didn't quite understood.
What i want: I have five tables and i want to return a select with all intersections of the main table with the other 4. I'm currently doing 2 selects and then a UNION. It works great, but i guess i could improve the performance doing in a single select.
Here is an example of my code:
SELECT column1 FROM tableA A
INNER JOIN table B ON A.column1 = B.column1
LEFT JOIN table D ON A.column1 = D.column1
LEFT JOIN table E A.column1 = E.column1
WHERE B.column2 IS NOT NULL
AND B.column3 = '7'
AND ( (D.column2 = 'x' OR D.column3 = 'y') OR (E.column2 = 'x' OR E.column3 = 'y') )
UNION
SELECT column1 FROM tableA A
INNER JOIN table C ON A.column1 = C.column1
LEFT JOIN table D ON A.column1 = D.column1
LEFT JOIN table E A.column1 = E.column1
WHERE C.column2 IS NOT NULL
AND C.column3 = '7'
AND ( (D.otherColumn2= 'x' OR D.otherColumn3 = 'y') OR (E.otherColumn2 = 'x' OR E.otherColumn3 = 'y') )
About the tables.
Table A have the column1 shared with all the other tables:
(int) column1
Tables B and C have the same structure as follows:
(int) column1 | (int) column2 | (varchar) column3
And tables D and E also have the same structure:
(int) column1 | (varchar) otherColumn2 | (varchar) otherColumn3
As we can see, both selects are pretty much the same, with the exception of the table B and C.
I asked this question without the full code and #Kevin solved it. But with this extra information, and trying to follow his example, i changed the code to:
SELECT column1 FROM tableA A
LEFT JOIN table B ON (A.column1 = B.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7')
LEFT JOIN table C ON (A.column1 = C.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7')
LEFT JOIN table D ON A.column1 = D.column1
AND (D.otherColumn2 = 'x' OR D.otherColumn3 = 'y')
LEFT JOIN table E A.column1 = E.column1
AND (E.otherColumn2 = 'x' OR E.otherColumn3 = 'y')
WHERE
B.column1 is not null
or c.column1 is not null
or D.column1 is not null
or E.column1 is not null
But i getting a lot of extra results. I hope i'm making myself clear here, and if not, let me know and i will update this question.
You can always use exists:
select a.*
from tablea a
where exists (select 1 from tableb b where a.column1 = b.column1 and b.column3 = 7) or
exists (select 1 from tablec c where a.column1 = c.column1 and c.column3 = 7);
When you use join, you run the risk of getting duplicate rows -- and then you might do extra work to remove the duplicates. All unnecessary with exists.
And, for performance, you want indexes on tableb(column1, column3) and tablec(column1, column3).
This should get you what you want. However, I don't know that performance will be any better.
SELECT A.column1 FROM tableA A
LEFT JOIN tableB B ON A.column1 = B.column1
AND B.column2 IS NOT NULL
AND B.column3 = '7'
LEFT JOIN tableD d ON b.column1 = D.column1
LEFT JOIN tableE e ON B.column1 = E.column1
LEFT JOIN tableC C ON A.column1 = C.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7'
LEFT JOIN tableD d2 ON c.column1 = d2.column1
LEFT JOIN tableE e2 ON c.column1 = e2.column1
WHERE (B.column1 is not null
and (d.othercolumn2 = 'x' or d.othercolumn3='y' or e.othercolumn2 = 'x' or e.othercolumn3='y')
)
or (c.column1 is not null
and (d2.othercolumn2 = 'x' or d2.othercolumn3='y' or e2.othercolumn2 = 'x' or e2.othercolumn3='y')
)
You can check it on sqlfiddle

Case in SQL join statement

I have to use a conditional statement in join:
select * from A inner join B
on A.id = B.id
if B.id is null or B.id = '' or A.id is null or A.id = '' it should be A.name = B.name, instead of A.id = B.id
I have to use a conditional statement in join:
select * from A inner join B
on A.id = B.id
if B.id is null or B.id = '' it should be A.id2 = B.id2 instead of A.id = B.id.
Is it correct if I do something like this:
select *
from A inner join B on
(B.id is not null and B.id <> '' and A.id is not null and A.id <> '' and A.id = B.id) or
((B.id is null or B.id = '' or A.id is null or A.id = '') and A.name = B.name)
I think you will want something like this:
select * from A
inner join Bid on
(Bid.id is not null and Bid.id <> '' and A.id is not null and A.id <> '' and A.id = Bid.id)
inner join Bname on
((Bname.id is null or Bname.id = '' or A.id is null or A.id = '') and A.name = Bname.name)
that is to join on the B table twice, one join for when id is not null and the second join when id is null and you join on the name column instead. This works effectively like a case statement because the two joins to the B table are mutually exclusive.
Try this
select * from A inner join B
on (A.id = B.id) or
(A.name = B.name and (B.id is null or B.id = '' or A.id is null or A.id = ''))
try this code
DECLARE #b varchar(50)=(SELECT id FROM b)
DECLARE #a varchar(50)=(SELECT id FROM a)
if ((#b in (null , '')) and (#a in (null , '')))
BEGIN
select * from A inner join B
on
A.name = B.name
END
else
BEGIN
select * from A inner join B
on A.id = B.id
END

build where clause to verify only once first clause is met

I have following sql select:
select ...
from table1 a, table2 b
where
a.column = 'ABC' and
a.column2 = b.column2
I would like to only check if a.column2 = b.column2 when a.column = 'ABC'.
How do I do that?
Thanks
I'm not sure from your question tag if you're trying to figure out how to do this with a JOIN specifically (as opposed to how you did it with the WHERE clause), but anyway -- a couple of ways:
1) --with WHERE clause
select ...
from
table1 a
INNER JOIN table2 b
ON a.column2 = b.column2
where
a.column = 'ABC'
2) --WITHOUT WHERE CLAUSE
select ...
from
table1 a
INNER JOIN table2 b
ON a.column2 = b.column2
AND a.column = 'ABC'
Try this. It will check column2 only when column is 'ABC':
select ...
from table1 a, table2 b
where
(a.column = 'ABC' and
a.column2 = b.column2) or a.column <> 'ABC'