I have a table called TableA that stored list of event like this
Event_Id Event_Name
1 Found in AD
2 Found in AAD
I have another table call Table B and it look something like this
Event_Id UserName Extra
NULL David Found In AAD
1 James Found in AD
Null Ronal Null
I'm just trying to update only a missing/Null value in TableB Event_ID column based on comparing Table1 Event_Name and TableB Extra columns.
I'm doing manually process like this for now so I would be really appreciated If I can get any help on how to join directly between the two table and update it.
Update Table B
Set Event_Id = case
when Extra = 'Found in AAD' then 2
end
You can use a simple sub-query in your UPDATE to do that.
UPDATE TableB SET
Event_Id = (SELECT Event_Id from TableA a where a.Event_Name = TableB.Extra)
WHERE Event_Id is null;
This will look for any matches on the Event_Name and Extra_Name and update the Extra table's Event_Id based on the match.
SQL:
UPDATE
Extra_Data
SET
Extra_Data.Event_Id = a.Event_Id
FROM
Event_Data a
INNER JOIN Extra_Data b ON a.Event_Name = b.Extra_Name
WHERE
b.Event_Id IS NULL;
Results:
| Event_Id | UserName | Extra_Name |
|----------|----------|--------------|
| 2 | David | Found In AAD |
| 1 | James | Found in AD |
| (null) | Ronal | (null) |
SQL Fiddle:
http://sqlfiddle.com/#!18/3a2ea/7
update table_b
set table_b.Event_Id = table_a.Event_Id
from table_b
JOIN table_a
ON table_b.extra = table_a.Event_Name
Related
I have two tables on SQL-Server. One containing clients, and one a client profile lookup table. So a bit like this (note that Fred doesn't have any values in the lookup table):
Table: Clients Table: Profile
ID | Name | Status ClientID | Type | Value
----------------------- -----------------------
1 | John | Current 1 | x | 1
2 | Peter | Past 1 | y | 2
3 | Fred | Current 2 | x | 3
2 | y | 4
I then am trying to create a tmp table that needs to contain all current clients like this:
ID | Name | TypeY
==================
1 | John | 2
3 | Fred |
My knowledge of SQL is limited, but I think I should be able to do this with a Left Join, so I tried this (#tmpClient is already created):
insert into #tmpClient
select a.ID, a.Name, b.Value
from Clients a
left join Profile b
on a.ID = b.ClientID
where a.Status = 'Current' and b.Type = 'y'
However this will always miss Fred out of the temporary table. I am probably doing something very simple wrong, but as I said I am missing the SQL skills to work this one out. Please can someone help me with getting this query right.
You have to move the predicate concerning the second table of the LEFT JOIN operation from WHERE to ON clause:
insert into #tmpClient
select a.ID, a.Name, b.Value
from Clients a
left join Profile b
on a.ID = b.ClientID and b.Type = 'y'
where a.Status = 'Current'
Provided the following structure and data:
CREATE TABLE "CHANGES" (
"ID" NUMBER(38),
"LAST_UPD_DATE" DATE DEFAULT SYSDATE
);
CREATE TABLE "EXPORT_LOG" (
"ID" NUMBER(38),
"LAST_EXPORT" DATE DEFAULT SYSDATE
);
Table CHANGES contains:
----------------------------
| ID | LAST_UPD_DATE |
----------------------------
| 123 | 12-MAY-16 12.23.23 |
| 124 | 12-MAY-16 12.24.23 |
| 125 | 12-MAY-16 12.11.23 |
----------------------------
and EXPORT_LOG
----------------------------
| ID | LAST_EXPORT |
----------------------------
| 124 | 12-MAY-16 12.23.12 |
| 125 | 12-MAY-16 12.12.24 |
----------------------------
I need to get the records in CHANGES that either don't exist in EXPORT_LOG or, if exists, get records with LAST_UPD_DATE later than LAST_EXPORT.
So in the above example, I should be getting 123 and 124.
I'm trying different JOINs but I cannot seem to get the result I want:
INNER JOIN is used for intersections, LEFT JOIN gets ALL of first table, but only those of second table that match a condition you set - none of these is what I want. So is the solution some sort of UNION?
Try this:
SELECT t1.*
FROM CHANGES AS t1
LEFT JOIN EXPORT_LOG AS t2 ON t1.ID = t2.ID
WHERE (t2.ID IS NULL) OR (t1.LAST_UPD_DATE > t2.LAST_EXPORT)
This will return all records of CHANGES table that don't have a match in EXPORT_LOG table plus the records of CHANGES table that have a LAST_UPD_DATE that is later than LAST_EXPORT.
One method is to translate the conditions directly using exists:
select c.*
from changes c
where not exists (select 1 from export_log el where c.id = el.id) or
not exists (select 1 from export_log el where c.id = el.id and el.last_export > c.last_upd_date);
This can be simplified to:
select c.*
from changes c
where not exists (select 1 from export_log el where c.id = el.id and el.last_export > c.last_upd_date);
Please use the below mentioned code and provide me the feedback. It should work as per your requirement.
SELECT CH.ID, CH.LAST_UPD_DATE
FROM CHANGES CH, EXPORT_LOG EL
WHERE CH.ID = EL.ID(+)
AND ((EL.ID IS NULL) OR (CH.LAST_UPD_DATE > EL.LAST_EXPORT));
Edit: The answer given by mathguy works perfectly. But I really wanted to understand why the first update statement isn't working and second one does. I know that + operator is not suggested, but in this case as the second table was in subquery, I had to use it.
Short Question. (Detailed explanation and Create/Insert statements below)
What is the difference between these 2 update statement and why first one is not working as expected, whereas second one does.
update d_dim d
set FLAG=
(select case when t.id is null then 'N' else 'Y' end as FLAG
from t_temp t
where d.id=t.id(+)
);
And
update d_dim d
set FLAG=
(select case when t.id is null then 'N' else 'Y' end as FLAG
from t_temp t,d_dim d1
where d1.id=t.id(+)
and d1.id=d.id
);
Detailed Explanation
I am trying to replicate a workplace scenario. Unfortunately SQLFiddle for Oracle is not working so couldn't create fiddle demo.
I have 2 tables, d_dim(ID,FLAG) and t_temp(ID) like below
select * from d_dim;
+----+------+
| ID | FLAG |
+----+------+
| 1 | |
| 2 | |
| 3 | |
| 4 | |
+----+------+
select * from t_temp;
+----+
| ID |
+----+
| 1 |
| 3 |
+----+
Now I need to set the FLAG in d_dim as Y or N.
If ID exists in t_temp the set it Y. Else set it N.
So expected output should be like.
+----+------+
| ID | FLAG |
+----+------+
| 1 | Y |
| 2 | N |
| 3 | Y |
| 4 | N |
+----+------+
This is the update statement I am using (Using (+) as in this case I need left join from d_dim to t_temp
update d_dim d
set FLAG=
(select case when t.id is null then 'N' else 'Y' end as FLAG
from t_temp t
where d.id=t.id(+)
)
--4 rows updated.
But ID 2 and 4 are updated as NULL.
select * from d_dim;
+----+------+
| ID | FLAG |
+----+------+
| 1 | Y |
| 2 | |
| 3 | Y |
| 4 | |
+----+------+
If I use just the select clause after plugging in d_dim table, I get correct output.
select d.id,
case when t.id is null then 'N' else 'Y' end as FLAG
from t_temp t,d_dim d
where d.id=t.id(+)
order by id
+----+------+
| ID | FLAG |
+----+------+
| 1 | Y |
| 2 | N |
| 3 | Y |
| 4 | N |
+----+------+
I did some hit and trial and came up with this query, which seems to be working
update d_dim d
set FLAG=(select case when t.id is null then 'N' else 'Y' end as FLAG
from t_temp t,d_dim d1
where d1.id=t.id(+)
and d1.id=d.id);
select * from d_dim;
+----+------+
| ID | FLAG |
+----+------+
| 1 | Y |
| 2 | N |
| 3 | Y |
| 4 | N |
+----+------+
So my question is that
Why the initial update statement doesn't work properly and why is it
updating null for id 2 and 4.
Please find the Create and Insert statements below
CREATE TABLE d_dim (id int, flag varchar2(4));
INSERT ALL INTO d_dim (id, flag) VALUES (1, NULL)
INTO d_dim (id, flag) VALUES (2, NULL)
INTO d_dim (id, flag) VALUES (3, NULL)
INTO d_dim (id, flag) VALUES (4, NULL)
SELECT * FROM dual;
CREATE TABLE t_temp (id int)
;
INSERT ALL
INTO t_temp (id) VALUES (1)
INTO t_temp (id) VALUES (3)
SELECT * FROM dual;
In the second query you have an outer join. In the first query you don't have any kind of join; you simply have a select from t, with a where clause where there is a (+) after t.id. I don't know why that syntax doesn't return an error; but when d.id doesn't exist in t, that subquery returns no rows, and that's how update works when the update value is supposed to be the output of a scalar subquery: if the subquery returns no rows, the update statement will update the field with NULL.
You didn't ask for a different way to make the update work, but if you want to see one, here it is. No doubt you know how to do this; offering it for the benefit of other forum members.
update d_dim
set FLAG = case when id in (select id from t_temp) then 'Y' else 'N' end;
EDIT: It seems the OP didn't fully understand my point so here are more details.
The Oracle documentation states explicitly:
•The (+) operator does not produce an outer join if you specify one table in the outer query and the other table in an inner query.
https://docs.oracle.com/cd/B28359_01/server.111/b28286/queries006.htm
(under the heading "Outer Joins", after the "See Also" box)
An update statement would update based on whether the condition was satisfied for the update as specified in the subselect clause.
When you mention
update d_dim d
set FLAG=
(select case when t.id is null then 'N' else 'Y' end as FLAG
from t_temp t
where d.id=t.id(+)
);
This statement would be executed only when d.id is equal to t.id. In your case, for id=2, d.id is 2, t.id is null. 2 is NOT equal to null, so the update has no effect on id 2.
I have two tables:
TABLE A
id | user_id | name
------+-----------+-------
1 | 122 | 'Bill'
2 | 123 | 'Jim'
3 | 124 | 'Sally'
TABLE B
id | user_id | title
------+-----------+-------
1 | 122 | 'Boss'
2 | 999 | 'Manager'
3 | 124 | 'Worker'
I want to update all of A with name = 'foo' where there is no matching user_id in table B. Do not update the row if user_id exists in table B.
So in this case it would only update Jim to the name 'foo'.
NOT EXISTS should be simplest, safest & fastest:
UPDATE tbl_a a
SET name = 'foo'
WHERE NOT EXISTS (SELECT FROM tbl_b b WHERE b.user_id = a.user_id);
This also works as expected with NULL values. As opposed to NOT IN. See:
https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_NOT_IN
With Rails:
user_ids_in_table_b = MobelB.pluck(:user_id)
ModelA.where.not(user_id: user_ids_in_table_b).update_all(name: 'foo')
You need to change the MobelA & MobelB models name to your models name in your app.
In pure SQL:
UPDATE table_a
SET name = 'foo'
WHERE user_id NOT IN (SELECT user_id FROM table_b);
This is probably very easy, but it's Monday morning. I have two tables:
Table1:
Field | Type | Null | Key | Default | Extra
id | int(32) unsigned | NO | PRI | NULL | auto_increment
group | int(32) | NO | | 0 |
Table2:
Field | Type | Null | Key | Default | Extra
group | int(32) | NO | | 0 |
Ignoring other fields...I would like a single SQL DELETE statement that will delete all rows in Table1 for which there exists a Table2.group equal to Table1.group. Thus, if a row of Table1 has group=69, that row should be deleted if and only if there exists a row in Table2 with group=69.
Thank you for any help.
I think this is what you want:
DELETE FROM `table1`
WHERE `group` in (SELECT DISTINCT `group` FROM `table2`)
I think this way is faster:
DELETE FROM t1 USING table1 t1 INNER JOIN table2 t2 ON ( t1.group = t2.group );
The nice solution is just writing the SQL as you say it yourself already:
DELETE FROM Table1
WHERE
EXISTS(SELECT 1 FROM Table2 WHERE Table2.Group = Table1.Group)
Regards,
Arno Brinkman
Something like this
delete from table1 where group in (select group from table2)
Off the top of my head:
delete from Table1 where id in (select id from table1 inner join table2 on Table1.group = Table2.group)
I did this a little differently than other posters -- I think if there is a large number of rows on Table2 this might be better. Can someone please set me straight on that?
you can delete either table rows by using its alias in a simple join query like
delete a from table1 a,table2 b where a.uid=b.id and b.id=57;
here, you might specify either a or b to delete the corresponding table rows