I have three tables and I have to write one query to update table 1 row from table 3 and the only matching columns I have is in table 2.
Table 1 which has incorrect data:
Table 3 has the correct data:
I did try to write a query and execute it but it gives me an error saying there are too many rows too select which is true I do have many rows to correct but it still wouldn't correct. What do you think I should do. This is my query so far.
UPDATE Table1
SET Table1.Number = (SELECT Table3.Number
FROM Table2
FULL OUTER JOIN Table1 ON Table1.ID = Table2.ID
FULL OUTER JOIN Table3 ON Table3.Signin = Table2.Signin
WHERE (Table2.ID = Table1.ID)
AND (Table1.Number = 'xxx'))
WHERE (Tale1.Number = 'xxx')
In Where clause of JOIN query need to modify as multiple records are generating by inappropriate condition.Try to use Table3 components instead of using Table1 in joining query where clause.
UPDATE Table1
SET Table1.NUMBER = (SELECT table3.NUMBER FROM Table1 FULL OUTER JOIN Table2
ON Table1.ID = Table2.ID
FULL OUTER JOIN Table3
ON Table2.SIGNIN = Table3.SIGNIN
WHERE Table3.SIGNIN = 100) // This is the point where you need to modify your code
WHERE Table1.ID = 1;
ONLINE DEMO HERE
It actually worked after I removed this line from my query.
FULL OUTER JOIN Table1 ON table1.ID = Table2.ID
Thanks for the help.
You are fairly close. When doing the update though unless you are wanting to clear value for t1.number when a record is not matched in t3, you will want to use INNER JOIN. FULL OUTER JOIN would mean you are trying to update rows in t1 that don't exist but a LEFT JOIN you would update t1.number to NULL if a record in t3 doesn't exist.
UPDATE t1
SET t1.Number = t3.Number
FROM
Table1 t1
INNER JOIN Table2 t2
ON t1.Id = t2.Id
INNER JOIN Table3 t3
ON t2.Signin = t.3.Signin
WHERE
t1.number <> t3.number
--Or if you have nulls something like
--ISNULL(t1.number,'xxx') <> ISNULL(t3.number,'xxx')
-- if you only want to update when t1.number = 'xxx' then
--t1.number = 'xxx'
t1,t2,t3 are table aliases that I created by adding the alias after table name. By using join syntax rather than a sub select you simplify your were conditions. In sql-sever if more than 1 record in t2 & t3 match it will select one row randomly in the case of a one to many relationship. If you want a specific record when not one to one relation you can use window functions and common table expressions (cte) to limit t3 to the exact record you want to use.
Related
Initially, I have a query like below, doing a join on 1=1. (It's simply doing a cross join, which selects all rows from the first table and all rows from the second table and shows as a cartesian product, i.e. with all possibilities.)
SELECT * FROM Table1 t1
JOIN Table2 t2 ON 1=1
Problem: Optimize this query in such a way, it will show only the records for a particular ID and if we don't have an ID or have a NULL in the ID then it will show the result same as previously(1=1). So I wrote the script below.
Declare #T2id as int;
Set #T2id = 123;
SELECT * FROM Table1 t1
JOIN Table2 t2 ON
-- left side of join on statement
CASE
WHEN #T2id Is NULL
THEN 1
ELSE
t2.Id
END
=
-- right side of join on statement
CASE
WHEN #T2id Is NULL
THEN 1
ELSE
#T2id
END
Can anyone confirm, is it good or we can have a better approach than this?
I think your way of presenting a cross-join is something I haven't seen before.
My view is it's simpler to read and understand if you just:
SELECT *
FROM Table1 t1, Table2 t2
As for the question, assuming SQL Server (you didn't tag the RDBMS, but I guess from your variable declaration) you might consider:
IF ISNULL(#T2id,1) = 1
SELECT *
FROM Table1 t1, Table2 t2;
ELSE
SELECT *
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.id = t2.id
WHERE t2.id = #T2id;
I want to fetch all records with all columns of a table, Records which are not in the other 2 tables. Please help.
I have tried below query, it is working fine for comparing one column. But I want to compare 5 columns.
select * from A
WHERE NOT EXISTS
(select * from B b where b.id=a.id) AND
NOT EXISTS
(select * from C c where c.id=a.id)
A general solution might look like:
SELECT t1.*
FROM table1 t1
WHERE NOT EXISTS (SELECT 1 FROM table2 t2 WHERE t2.id = t1.t2_id) AND
NOT EXISTS (SELECT 1 FROM table3 t3 WHERE t3.id = t1.t3_id);
This assumes that you want to target table1 for records, ensuring that no matches can found in table2 and table3.
I prefer this approach:
SELECT t1.*
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t1.id = t2.t1_id
LEFT JOIN table3 AS t3
ON t1.id = t3.t1_id
WHERE t2.id IS NULL
AND t3.id IS NULL;
While this might be a bit less intuitive than using sub queries I think odds of making mistakes with aliases are less likely as in the example below, which happens more often than you might expect:
SELECT *
FROM table1
WHERE NOT EXISTS (SELECT 1 FROM table2 WHERE id = id) AND
NOT EXISTS (SELECT 1 FROM table3 WHERE id = id);
To your question about checks on 5 columns, that can still be done using either of these methods by adding conditions either in the left joins or in the where clause of each sub query.
I have this SQL...
UPDATE table1 t1
SET (t1.wert) =
(select t2.bezeichnung from table2 t2
where t1.id = t2.cpbezeichnung)
where t1.id = t2.cpbezeichnung
... which I cant run because it says me that it doesnt know t2.cpbezeichnung in line #5.
How can I fix it?
Table with alias t2 is not defined for UPDATE query, so it's clearly not known at line 5. Table t2 is defined only inside subquery on lines 3 and 4.
What exactly are you trying to achieve with condition on line 5?
If do you want prevent setting NULL into t1.wert for rows where there is no appropriate record in table t2, then you need to replace condition on line 5
UPDATE table1 t1
SET (t1.wert) =
(select t2.bezeichnung from table2 t2 where t1.id = t2.cpbezeichnung)
where t1.id IN (SELECT t2.cpbezeichnung from table2)
This will set values in t1.wert only for records where t1.id exists in t2.cpbezeichnung.
The t2 alias (along with table2) is only visible in the subquery. My guess is that you want
UPDATE table1 t1
SET t1.wert = (select t2.bezeichnung
from table2 t2
where t1.id = t2.cpbezeichnung)
where exists (select 1
from table2 t2
where t1.id = t2.cpbezeichnung)
which updates every row where there is a match between the two tables. If that's not what you want, posting a test case would be helpful.
When using correlated subqueries you cannot use an alias from the inner query in the outer query.
The outer query knows nothing about the inner query except its results.
Ref
You will have to use a Inner join on the two tables.
Something like
UPDATE table1 t1 INNERJOIN table t2 ON your_table_condition SET t1.wert = (select t2.bezeichnung from t2 where t1.id = t2.cpbezeichnung) where t1.id = t2.cpbezeichnung
I have a table (Table1) which has a composite primary key(Column1 + Column2). I am using it as a foreign key in another table (Table2).
Now I want to a SELECT statement to select all records from Table1 and Table2.
But its returning me 0 rows, because table2 is Empty. I want all records from table1 and if it does not exist in table2, value of Columns in Table2 should be null.
I know, I only need to Join it. But I am not getting it right.
Thanks
SELECT * FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.Id = T2.FK
FK is your foreign key on the second table.
A Left Join will return all rows from table1 even if they don't exist in table2.
You need an outer join
SELECT *
FROM table1
LEFT OUTER JOIN table2
ON table1.column1 = table2.column1
AND table1.column2 = table2.column2
Left means preserve all rows from the left (first) table in the query.
You need a LEFT JOIN
SELECT Table1.*, Table2.*
FROM Table1
LEFT JOIN Table2 ON Table1.Column1 = Table2.Column2
Try that out.
Use LEFT JOIN for join you tables. See SQL SERVER JOINS to understand the concept.
SELECT ID
(
Select ID from Table1
where Table1.ID=#ID
)T1
Left Outer join
(
Select top 1 Table2.ID from Table2 join Table3 on table3.ID=Table2.ID
order by Table2.ID DESC
)T2 on T2.ID=T1.ID
This is just an example of the actual stored procedure I have with me, the problem which I am facing is that I'm unable to retrieve the values from T2 it just returns as NULL but when I change it Top 5 i am able to retrieve the values. Is this Join correct, is it necessary to have where part inside left outer join in order to retrieve the values?
If you are using TOP you need to decide on all selects (all three) how your data should be ordered so you can have some control on which values you are getting back, and maybe also being more specific on what you filter.
A couple of observations.
There's no ORDER BY clause for your T1 SELECT, so how do you know which TOP 250 is being returned?
If T2 returns NULL, then there is no match between T1 and T2, possibly due to my first point?
What exactly are you trying to accomplish?
You could try something like this:
SELECT
TOP 250 Table1.ID
FROM
Table1
LEFT OUTER JOIN
Table2 ON Table2.ID = Table1.ID
LEFT OUTER JOIN
Table3 ON Table3.ID = Table2.ID
WHERE
Table1.ID = #ID
ORDER BY
Table1.ID DESC