I want to update table value based on another table max value - mysql

I have two tables A and B(oracle database). Table B has two columns Id and mdate, where id is primary key. Table A has two columns Id and mdate where id is foreign key. I want to update table B mdate value which should be max mdate value from table A for matching Id.
Update b
set mdate= (select max(mdate) from a group by Id)
where b.id = a.id;

You're very close. The WHERE clause needs to be moved into the subquery, to make it a correlated subquery. Also, the parameter to UPDATE is a table name, not a column name.
UPDATE b
SET mdate = (SELECT MAX(mdate) FROM a WHERE b.id = a.id)
In MySQL you can also do it with a JOIN:
UPDATE b
JOIN (SELECT id, MAX(mdate) AS mdate
FROM a
GROUP BY id) AS a ON a.id = b.id
SET b.mdate = a.mdate

Update b
set(b.mdate) = (select MAX(a.mdate) from a where b.id = a.id)
where exists ( select 1 from a where b.id = a.id);
Thanks to Mr. Barmar.

Related

How to use GROUP_CONCAT on multiple JOIN

I am currently retrieving data from multiple tables using a cus_id as the initial query. From here I have multiple tables that can have various rows of data that I would like to retrieve and use GROUP_CONCAT to return this data in a single row. At the moment, my query is returning duplicate data based on the max number of rows returned by one of the group concats.
SELECT a.id,c.x,c.y,c.z
GROUP_CONCAT(a.column_a) AS aca,
GROUP_CONCAT(a.column_b) AS acb,
GROUP_CONCAT(b.column_a) AS bca,
GROUP_CONCAT(b.column_b) AS bcb,
FROM `table_a` a
INNER JOIN `table_b` b ON a.id = b.id
INNER JOIN `table_c` c ON a.id = c.id
WHERE a.id = ?
Also, in this scenario, what is the correct join method to use. I am expecting all the fields I am requesting to have some sort of data.
Problem was resolved by using sub queries to isolate the GROUP_CONCAT requests. This allowed me to get only the data I wanted without duplicate results manipulated by other JOIN requests.
SELECT a.id,c.x,c.y,c.z
(SELECT GROUP_CONCAT(column_a) FROM table_a) AS aca,
(SELECT GROUP_CONCAT(column_b) FROM table_a) AS acb,
(SELECT GROUP_CONCAT(column_a) FROM table_b) AS bca,
(SELECT GROUP_CONCAT(column_b) FROM table_b) AS bcb,
FROM table_a a
INNER JOIN `table_c` c ON a.id = c.id
WHERE a.id = ?
Aggregate before joining. Somthing along the lines of:
select
a.*,
b.grp_a,
b.grp_b,
c.grp_x,
b.grp_y
from table_a a
join
(
select
a_id,
group_concat(a order by b_id) as grp_a,
group_concat(b order by b_id) as grp_b
from table_b
group by a_id
) b on b.a_id = a.id
join
(
select
a_id,
group_concat(x order by c_id) as grp_x,
group_concat(y order by c_id) as grp_y
from table_c
group by a_id
) c on c.a_id = a.a_id
order by a.a_id;

Left join is returning multiple rows from Table B corresponding to ID present in Table A

I have 2 tables in my SQL database. Let's call them Table A and Table B.
I have joined both the tables using left join on ID = AID. Table A has a field by name ID and Table B has field AID and Price.
The problem is Table B can have multiple prices for the ID present in Table A.
The requirement is - If only one price is present in Table B corresponding to ID in table A then it should return that price.
If more than one price is present in table B for an ID in table A then I should get the price as Zero/null.
Query -
SELECT DISTINCT A.ID,B.Price
from A
left join B
on A.ID = B.AID
where "some condition"
Use Count() with Over() window function to find the count of records for each ID then based on count return the price
Try this way
SELECT DISTINCT A.ID,
case when count(1) over(partition by A.ID) > 1 then NULL else B.Price end
from A
left join B
on A.ID = B.AID
For Mysql
SELECT DISTINCT a.id,
CASE
WHEN c.aid IS NULL THEN NULL
ELSE b.price
END
FROM a
LEFT JOIN b
ON a.id = b.aid
LEFT JOIN (SELECT aid
FROM b
GROUP BY aid
HAVING Count(1) = 1) c
ON a.id = c.aid
For SQL Server (should work for MySQL too). One sub-query (you can put in CTE) that shows only AIDs that have only one price:
SELECT A.ID,
B.Price
FROM A
LEFT JOIN (
SELECT AID
FROM B
GROUP BY AID
HAVING COUNT(Price) = 1
) as C
ON C.AID = A.ID
LEFT JOIN B
ON C.AID = B.AID
Use below query. It should work.
SELECT A.ID, o.Price
FROM A
OUTER APPLY
(
SELECT IIF(COUNT(B.Price)>1,NULL,MAX(B.Price)) AS Price
FROM B
WHERE B.AID = A.ID
) AS o;

Get only one row from inner join

I have two tables. Primary key from table A is primary key in table B with another column.
So structure is like this.
Table A
id - PRIMARY
total_amount
Table B
id - PRIMARY
another_id PRIMARY
status
So i can have id from table A appear multiple times in table B.
My problem is that this query
SELECT IFNULL(SUM(total_amount), 0) AS amount
FROM tableA AS a
INNER JOIN tableB AS b
ON a.id = b.id
WHERE a.id = 10
AND status <> 'UNKNOWN'
sometimes returns more in amount the it should.
If total_amount on id 10 is 2, and that same id 10 repeats in table b three times my amount will be 6 instead of 2.
Is there a way I can avoid that. Some other way to write this query.
Thank you.
Use exists instead:
SELECT IFNULL(SUM(total_amount), 0) AS amount
FROM tableA a
WHERE EXISTS (SELECT 1
FROM tableB AS b
WHERE a.id = b.id AND b.status <> 'UNKNOWN'
);
DISTINCT the list of ids returned from tableB
SELECT
IFNULL(SUM(total_amount), 0) AS amount
FROM
tableA AS a INNER JOIN (SELECT DISTINCT id FROM tableB WHERE [status] <> 'UNKNOWN') AS b ON a.id = b.id
WHERE
a.id = 10

SQL Join over two tables

here is my problem:
I have two tables. Every entry of table A has several entries in table B matched over an ID. I now want to get all entries of table A with one data entry of table B - the one with the highest ID in this table.
Table A has an ID
Table B has an own ID and ID_OF_TABLE_A (for the relation between both)
Table A has one to many relation to Table B. I want all Entries of Table A, matched with the one with the highest ID out of B. Is there any way to realize this in an SQL Statement? I tried all kinds of joins since I need the information of that matched entry in the outcome of the select.
How about
SELECT *
FROM tableA a
INNER JOIN tableB b ON a.ID = b.ID_OF_TABLE_A
WHERE b.ID = (SELECT MAX(ID) FROM tableB c WHERE b.ID = c.ID)
Try this:
SELECT a.*, b.*
FROM tableA a
LEFT OUTER JOIN (SELECT b.*
FROM tableB b
INNER JOIN (SELECT ID_OF_TABLE_A, MAX(ID) bID
FROM tableB
GROUP BY ID_OF_TABLE_A
) c ON b.ID_OF_TABLE_A = c.ID_OF_TABLE_A AND b.ID = c.bID
) AS b ON a.ID = b.ID_OF_TABLE_A;
You can use an inline view where you filter the rows you need from table b with the help of the grouping clause and max function like so:
select a.*, b.*
from a
join (
select max(id) as id_b_max, id_a
from b
group by id_a
) b
on a.id = b.id_a;
Tested with:
create table a(id int);
create table b(id int, id_a int);
insert a values (1);
insert b values(1, 1);
insert b values(2, 1);
insert b values(3, 1);
select a.id, max(b.id)
from table_a a join table_b b on a.id = b.table_a_id
group by a.id
This should work. prefilter out the max id of the ID_OF_TABLE_A. and then join on that id.
SELECT A.*, B.*
FROM A
INNER JOIN ( SELECT max( ID ) AS id, ID_OF_TABLE_A
FROM B
GROUP BY ID_OF_TABLE_A) AS grp_b
ON grp_b.ID_OF_TABLE_A = a.ID
INNER JOIN B ON b.ID = grp_b.id

Turning the same column from 3 rows into 3 columns in another table

There are three tables, table a, table b, and table c. Table b combines id's from the other two tables to define a 1-to-(1 to 3) relationship between a and c. So any a will have between 0 and 3 c's.
Performing joins and multiple selects to do validation on objects based on these relationships is too costly. I am trying to get rid of table b altogether, and define the relationships, in order of c.id, in table a.
What is the update query I'm supposed to run? I tried this:
UPDATE a SET c_a = (SELECT c_id from b WHERE a_id = a.id LIMIT 0,1 ORDER BY c_id asc);
UPDATE a SET c_b = (SELECT c_id from b WHERE a_id = a.id LIMIT 1,1 ORDER BY c_id asc);
UPDATE a SET c_c = (SELECT c_id from b WHERE a_id = a.id LIMIT 2,1 ORDER BY c_id asc);
but that failed, because you cannot use LIMIT in a subquery in MySQL.
How do you do this in SQL?
This should work if you don't mind the order:
UPDATE a a, b b
SET a.c_a = b.c_id
WHERE a.id = b.a_id
UPDATE a a, b b
SET a.c_b = b.c_id
WHERE a.id = b.a_id
and a.c_a <> b.c_id
UPDATE a a, b b
SET a.c_c = b.c_id
WHERE a.id = b.a_id
and a.c_a <> b.c_id
and a.c_b <> b.c_id