How to Update table By following image? - mysql

I want to update my table like
Relation A.id = B.a_id

For MySQL:
UPDATE B
JOIN A ON B.email = A.email
AND B.a_id = A.id
SET B.email = '';
UPDATE B
JOIN (
SELECT *
FROM B
GROUP BY email, a_id
HAVING COUNT(*) > 1
) AS dp ON B.email = dp.email
AND B.a_id = dp.a_id
AND B.id != dp.id
SET B.email = '';

The first case, when exist email in table A:
update table_b b set email = '' where (select 1 from table_a a where a.email = b.email) = 1;
Next case, when email duplicate in table B:
update table_b b set email = '' where b.id in
(select
bb.id
from table_b bb
where bb.email in (
select bbb.email,count(*)
from table_b bbb
where bbb.email = b.email
having count(*) > 1
)
limit 1
)

A simple inner join would do the trick
UPDATE TableB
SET EMAIL='' --or set this to null
FROM TableA
INNER JOIN TableB ON
TableA.id = TableB.a_id AND
TableA.email = TableB.email
Where As for updating duplicates in the same Table i.e TableB i would opt for CTE and Row_number
WITH CTE AS(
SELECT id,a_id,email,
RN = ROW_NUMBER()OVER(PARTITION BY a_id,email ORDER BY id)
FROM TableB
)
UPDATE CTE SET email='' WHERE RN > 1

Related

MySQL find NON-matching values in 2 columns of different tables (in different DBs) with one efficient query

I have to update col_Foo and col_Bar in table B with the data in col_Foo and col_Bar in table A. The 2 tables have the same primary index id.
This need to be as efficient as possible, as unfortunately I'm compelled to poll the database very ofter and cannot rely on any event system.
This was my first attempt, which doesn't work but I think it makes it easy to understand what I'd like to achieve:
select B.*, A.foo, B.foo, A.bar, B.bar
from DB2.B-name as B
inner join DB1.A-name as A
on B.id = A.id
and (A.bar <> B.bar or A.foo <> B.foo)
The following does work, but I wonder if it could be made more efficient.
Or if maybe I'm better off just updating the whole column without checking for any mismatch.
SELECT A.id, A.foo, B.foo, A.bar, B.bar
FROM DB1.A-name AS A
WHERE A.id NOT IN (
(
SELECT A.id as idt
FROM DB1.A-name AS A
INNER JOIN DB2.B-name AS B
ON B.id = A.id
AND B.foo = A.foo
)
UNION ALL
(
SELECT A.id as idt
FROM DB1.A-name AS A
INNER JOIN DB2.B-name AS B
ON B.id = A.id
AND B.bar = A.bar
) t
GROUP BY idt
HAVING COUNT (*) = 2
)
EDIT: adding UPDATE version:
UPDATE DB2.B-name AS B
INNER JOIN DB1.A-name AS A
ON B.id = A.id
SET
B.foo = A.foo,
B.bar = A.bar
WHERE A.id NOT IN (
(
SELECT A.id as idt
FROM DB1.A-name AS A
INNER JOIN DB2.B-name AS B
ON B.id = A.id
AND B.foo = A.foo
)
UNION ALL
(
SELECT A.id as idt
FROM DB1.A-name AS A
INNER JOIN DB2.B-name AS B
ON B.id = A.id
AND B.bar = A.bar
) t
GROUP BY idt
HAVING COUNT (*) = 2
)

How to delete based on select query

I want to delete the rows of that are the result of this query
SELECT *
FROM a
LEFT JOIN b
ON a.id = b.id
WHERE b.id IS NULL;
How to do it?
I have tried:
DELETE
FROM a
LEFT JOIN b
ON a.id = b.id
WHERE b.id IS NULL;
But it is not working
Use not exists:
delete a from a
where not exists (select 1 from b where b.id = a.id);

query impossible for me?

I have 2 columns a and b with a 1:n relation:
A.id, a.text, a.b_id(fk), a.value --
B.id(pk), b.text etc
I want to create a query that returns the number of b.id with count(a.value=1) > 0
I tried this:
Select count(b.id)
from a.id
join b on a.b_id=b_id
group by b.id
having count(if(a.value=1),1,null))>0
...but without result. It seems simple but for me is a problem.
You don't need HAVING because standard INNER join won't return b rows without matching a rows anyway. You don't need GROUP BY either - use COUNT(DISTINCT ) instead:
SELECT COUNT(DISTINCT b.id) AS cnt
FROM b
JOIN a ON a.b_id = b.id
WHERE a.value = 1
This should do:
SELECT COUNT(*)
FROM TableB AS B
WHERE EXISTS(SELECT 1 FROM TableA
WHERE id = B.id
AND value = 1)
Try this:-
Select count(b.id) as x
FROM b
JOIN a ON a.b_id = b.id
WHERE a.value = 1
group by b.id
A simplification on #MarcinJuraszek's answer. If the foreign key can be trusted, there is no need to join table b:
SELECT COUNT(DISTINCT a.b_id) AS cnt
FROM a
WHERE a.value = 1 ;

can't specify target table for UPDATE in FROM clause

I am trying to execute the following query:
update table3 d set status = 'Complete'
where d.id in
(
select b.id from table1 a, table3 b, table2 c
where a.id = b.table1_id
and c.id = b.table2_id
and c.examId = 16637 -- will be passed in by user
and a.id in (46,47,48,49) -- will be passed in by user
);
So, I'm trying to update multiple rows of table3.
table3 is a join table between table1 and table2.
wrap it in a subquery, (thus creating a temporary table for the result). I'm also recommending to use ANSI SQL-92 format.
update table3 d
set status = 'Complete'
where d.id in
(
SELECT ID
FROM
(
select b.id
from table1 a
INNER JOIN table3 b
ON a.id = b.table1_id
INNER JOIN table2 c
ON c.id = b.table2_id
where c.examId = 16637 and
a.id in (46,47,48,49)
) xx
);
or by using JOIN
update table3 d
INNER JOIN
(
SELECT ID
FROM
(
select b.id
from table1 a
INNER JOIN table3 b
ON a.id = b.table1_id
INNER JOIN table2 c
ON c.id = b.table2_id
where c.examId = 16637 and
a.id in (46,47,48,49)
) xx
) y ON d.id = y.id
set status = 'Complete'

SQL LEFT JOIN only newest right column entry?

So I have two tables like this:
create table A
{
id int;
...
}
create table B
{
id int;
a_id int;
t timestamp;
...
}
A is one-to-many with B
I want to:
SELECT * FROM A LEFT JOIN B ON A.id = B.a_id ???
But I want to return exactly one row for each entry in A which has the B with the newest t field (or null for Bs fields if it has no B entry).
That is rather than returning all A-B pairs, I want to only select the newest one with respect to A (or A-null if no B entry).
Is there some way to express this in SQL? (I'm using MySQL 5.5)
LEFT JOIN is only concerned with ensuring every row in A is returned, even if there is no corresponding joined row in B.
The need for just one row needs another condition. MySQL is limitted in its options, but one could be:
SELECT
*
FROM
A
LEFT JOIN
B
ON B.id = A.id
AND B.t = (SELECT MAX(lookup.t) FROM B AS lookup WHERE lookup.id = A.id)
Another could be...
SELECT
*
FROM
A
LEFT JOIN
(
SELECT id, MAX(t) AS t FROM B GROUP BY id
)
AS lookup
ON lookup.id = A.id
LEFT JOIN
B
ON B.id = lookup.id
AND B.t = lookup.t
You could do the following:
SELECT A.*, B.*
FROM
A
LEFT JOIN
(SELECT B.a_id, MAX(t) as t FROM B GROUP BY B.a_id) BMax
ON A.id = BMax.a_id
JOIN B
ON B.a_id = BMax.a_id AND B.t = BMax.t
you first need to get the newest t from tableB in a subquery, then join it with tableA and tableB.
SELECT a.*, c.*
FROM tableA a
LEFT JOIN
(
SELECT a_ID, max(t) maxT
FROM tableB
GROUP BY a_ID
) b on a.a_id = b.a_ID
LEFT JOIN tableB c
ON b.a_ID = c.a_ID AND
b.maxT = c.t
try this:
SELECT *
FROM tableA A LEFT JOIN
(select a_id ,max(t) as max_t
from tableB
group by a_id )b
on A.id = b.a_id
and A.t=b.max_t