Updating values in one table based on another - mysql

I have following UPDATE query, but something is wrong when executing.
I'm trying to update values in table1 with values in table import_data, but I need the id from table ids... So the table ids links table1 and *import Simple, isn't it?
UPDATE table1
INNER JOIN import_data ON (
import_data.id = (
SELECT customer_id
FROM ids
INNER JOIN table1 ON (
table1.id = ids.link
)
WHERE ids.type = 'NORMAL'
)
)
SET table1.name = import_data.name;
table1
| id | name |
|----------|-----------|
| AA-00001 | Company 1 |
| AA-00002 | Company 2 |
| AA-00003 | Company 3 |
import_data
| id | name |
|--------|-------------------|
| 401000 | Updated company 1 |
| 401001 | Updated company 2 |
| 401002 | Company 3 |
ids
| link | id | type |
|----------|--------|--------|
| AA-00001 | 401000 | NORMAL |
| AA-00002 | 401001 | NORMAL |
| AA-00003 | 401002 | NORMAL |

Try:
update table1 t1
inner join (
select idata.name, ids.link
from import_data idata
join ids on ids.id = idata.id
where ids.type = 'NORMAL'
) x
on x.link = t1.id
set t1.name = x.name
Demo sqlfiddle

I think it's depends on database you're using. The relevant post is answered here - How can I do an UPDATE statement with JOIN in SQL?

I dont have mysql to check it, but it should work the way you want. Please check.
UPDATE table1
INNER JOIN ids
ON table1.id= ids.link
INNER JOIN import_data
on import_data.id = ids.id
SET table1.name = import_data.name
WHERE ids.type = 'NORMAL';

Related

Select records with same foreign key but different column value in another table (MYSQL)

Assume I have two tables with structures as defined.
Table1:
| question_id | question_type |
| ----------- | ------------- |
| 1 | 1 |
| 1 | 2 |
Table2:
| question_id | question_type | completed |
| ----------- | ------------- | --------- |
| 1 | 1 | 1 |
Now I want to select the record which has no entry in table2, I have done this but it does not work if the question_id is same.
Select * from table1 t1
left join table2 t2 on
(t1.question_id = t2.question_id and t1.question_type = 1) or
(t1.question_id = t2.question_id and t1.question_type = 2)
where t2.completed is null
and question_id = 1
The Problem is whenever there is a record for the same question_id with different type, no record is selected where as the result should give question_id = 1 with question_type = 2
I would use exists logic here:
SELECT t1.*
FROM Table1 t1
WHERE NOT EXISTS (
SELECT 1
FROM Table2 t2
WHERE t2.question_id = t1.question_id AND
t2.question_type = t1.question_type
);
If you wanted to use a join approach, we can try using a left anti-join here:
SELECT t1.*
FROM Table1 t1
LEFT JOIN Table2 t2
ON t2.question_id = t1.question_id AND
t2.question_type = t1.question_type
WHERE t2.question_id IS NULL;

mysql - How to update only the first row found from multiple duplicates rows

this is what I have, 2 tables, and i want to update table #2 with the stock from the first table, but i want to update only the first row of each duplicate.
+----+------+
|code|stock |
+----+------+
|5001| 40 |
|5002| 20 |
|5003| 60 |
+----+------+
+----+------+----+
|code|stock |lot |
+----+------+----+
|5001| | A | < Update this
|5001| | B |
|5002| | C | < Update this
|5003| | D | < Update this
|5003| | E |
+----+------+----+
So here i have the same product on two or more rows, and i want to update only the one from lot:A, lot:c, and lot: D, with the values from the first table.
How can i do this?
You could try using aupdate with join
update table2 t2
inner join (
select code, min(lot) lot
from table2
) t on t2.code = t.code and t2.lot = t.lot
inner join table1 t1 on t2.code = t1.code
set s2.stock = t1.stock

Display child and parent relationship (if any) in a same table

I have this table
| id |parent|name|
| 1 | NULL | E |
| 2 | NULL | B |
| 3 | 5 | U |
| 4 | 5 | X |
| 5 | NULL | C |
| 6 | NULL | A |
I would like the list, ordered by parent's name, of all ID whether they have a parent or not:
| id |parent|name|has_child|
| 6 | NULL | A | 0 |
| 2 | NULL | B | 0 |
| 5 | NULL | C | 1 |
| 3 | 5 | U | 0 |
| 4 | 5 | X | 0 |
| 1 | NULL | E | 0 |
Is it possible?
I have tried many things but never get the proper answer, and I don't really know how to add the 'has_child' column
SELECT
t1.parent,
t2.name
FROM tablename AS t1
INNER JOIN
(
SELECT MIN(id) AS id, parent
FROM tablename
GROUP BY parent
) AS t22 ON t22.id = t1.id AND t1.parent = t22.parent
INNER JOIN tablename AS t2 ON t1.parent = t2.id;
I would use a self join here:
SELECT DISTINCT
t1.id,
t1.parent,
t1.name,
1 - ISNULL(t2.id) has_child
FROM tablename t1
LEFT JOIN tablename t2
ON t1.id = t2.parent
ORDER BY
t1.id;
The join condition used here, which matches a given record as a parent to one or more children, is that the current id is also the parent of some other record(s). Note that we need SELECT DISTINCT here, because a given parent might match to more than one child record.
You can use a self join -- because you want the name of the parent and not the id -- and coalesce() for ordering:
select t.*,
(case when exists (select 1 from t tc where tc.parent = t.id)
then 1 else 0
end)
from t left join
t tp
on t.parent = tp.id
order by coalesce(tp.name, t.name), -- group rows by the parent, if any
(tp.name is null) desc, -- put parent first
t.name; -- order by children
I hope that you find this answer a little bit useful. The subquery gets the distinct id of parents and excludes the blanked fills.
SELECT *,
CASE WHEN id IN (SELECT DISTINCT parent
FROM tablename
WHERE parent IS NOT NULL)
THEN '1' ELSE '0'
END AS has_child
FROM tablename
ORDER BY name;
SELECT t1.id, t1.parent, t1.name, MAX(t2.parent is not null) has_child
FROM table t1
LEFT JOIN table t2 ON t1.id = t2.parent_id
GROUP BY t1.id, t1.parent, t1.name

How to select all rows from group, until occurrence of a value

I'm trying to extract all rows from same Group until I hit breakpoint value B. The example data below is ordered virtual table:
+----+--------+------------+
| ID | Group | Breakpoint |
+----+--------+------------+
| 1 | 1 | A |
| 2 | 1 | A |
| 3 | 1 | B |
| 4 | 1 | A |
| 5 | 2 | A |
| 6 | 2 | A |
| 7 | 2 | A |
| 8 | 3 | A |
| 9 | 3 | B |
+----+--------+------------+
This would be my result.
+----+--------+------------+
| ID | Group | Breakpoint |
+----+--------+------------+
| 1 | 1 | A |
| 2 | 1 | A |
| 5 | 2 | A |
| 6 | 2 | A |
| 7 | 2 | A |
| 8 | 3 | A |
+----+--------+------------+
Notice that when there are both A and B breakpoint values within a group, I want to have the rows until the first A value in this order. If there are only A values for a group like in group 2, I want to have all of the items in the group.
Here's a simple solution that uses no subqueries or GROUP BY logic.
SELECT t1.ID, t1.Group, t1.Breakpoint
FROM MyTable AS t1
LEFT OUTER JOIN MyTable AS t2
ON t1.ID >= t2.ID AND t1.`Group` = t2.`Group` AND t2.Breakpoint = 'B'
WHERE t2.ID IS NULL
For each row t1, try to find another row t2 with 'B', in the same Group, with an earlier ID. If none is found, the OUTER JOIN guarantees that t2.ID is NULL. That will be true only up until the desired breakpoint.
From you example above, you are not really grouping the results. you just need to display the records where Breakpoint is A:
Select * From Table
Where Breakpint ='A'
You may use NOT EXISTS
select *
from your_table t1
where not exists (
select 1
from your_table t2
where t1.group = t2.group and t2.id <= t1.id and t2.breakpoint = 'B'
)
or ALL can work as well if you never have NULL in id
select *
from your_table t1
where t1.id < ALL(
select t2.id
from your_table t2
where t1.group = t2.group and t2.breakpoint = 'B'
)
Assuming that we are ordering by ID column, we could do something like this:
SELECT d.*
FROM mytable d
LEFT
JOIN ( SELECT bp.group
, MIN(bp.id) AS bp_id
FROM mytable bp
WHERE bp.breakpoint = 'B'
GROUP BY bp.group
) b
ON b.group = d.group
WHERE b.bp_id > d.id OR b.bp_id IS NULL
ORDER BY d.group, d.id
This takes into account cases where there is no breakpoint='B' row for a given group, and returns all of the rows for that group.
Note that the inline view b gets us the lowest id value from rows with breakpoint='B' for each group. We can outer join that to original table (matching on group), and then conditional tests in the WHERE clause to exclude rows that follow the first breakpoint='B' for each group.
SQL tables represent unordered sets. Hence, there is no "before" or "after" a particular row.
Let me assume that you have some column that specifies the ordering. I'll call it id. You can then do what you want with:
select t.*
from t
where t.id < (select min(t2.id) from t t2 where t2.group = t.group and t2.breakpoint = 'B');
To get all rows when if there are no 'B':
select t.*
from t
where t.id < (select coalesce(min(t2.id), t.id + 1) from t t2 where t2.group = t.group and t2.breakpoint = 'B');

how to query display all data when not all related

I want to ask ..
If i have data but data related in another table
but i want the output is display all data
usually if data related in another table, I using INNER JOIN but the output just data have a relation, if dont have relation, its not display .. IF I using LEFT JOIN or RIGHT JOIN not all data displayed .. IF I using UNION data duplicated
this just example field .. field in real so many
TABLE A
ID | NAMA |
----------------------
1 | Rina |
2 | Deni |
3 | Muti |
4 | Sina |
5 | Sasa |
TABLE B
ID | Rumah |
----------------------
1 | Jabar |
2 | Jateng |
3 | Jatim |
OUTPUT THAT I WANT
ID | NAMA | Rumah
----------------------------------
1 | Rina | Jabar
2 | Deni | Jateng
3 | Muti | Jatim
4 | Sina | -
5 | Sasa | -
short version:
SELECT COALESCE(a.ID, t2.ID),
COALESCE(a.NAMA, '-')
COALESCE(b.Rumah, '-')
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
RIGHT JOIN TableB t2
ON a.ID = b.ID
If I understand your problem correctly, then a given ID might only have a first or last name, but not both. In this case, simply doing a left or right join will result in the loss of data. One approach here is to do a full outer join between your two tables on the ID, and then use COALESCE to handle possibly missing data appropriately.
SELECT COALESCE(t1.ID, t2.ID) AS ID,
COALESCE(t1.NAMA, '-') AS NAMA,
COALESCE(t2.Rumah, '-') AS Rumah
FROM TableA t1
LEFT JOIN TableB t2
ON t1.ID = t2.ID
UNION
SELECT COALESCE(t1.ID, t2.ID),
COALESCE(t1.NAMA, '-')
COALESCE(t2.Rumah, '-')
FROM TableA t1
RIGHT JOIN TableB t2
ON t1.ID = t2.ID