So i have 2 tables, both share the key "Product ID", i need to subtract where they match, for example
Table 1
Key Value
1 70
2 50
3 12
4 5
5 18
Table 2
Key Value
2 5
3 3
4 1
5 1
and i need the output
Output
Key Value
1 70
2 45
3 9
4 4
5 17
i tried
Update Table1
Set Table1.Count = Table1.Count - (
Select Table2.Count
From Table2
Where Table2.ID = Table2.ID
);
But this sets the value of Key 1 to null
I also tried putting a join before the Where, but that gave me the error:
ORA-01427: single-row subquery returns more than one row ORA-06512: at "SYS.DBMS_SQL"`
Your error message indicates that you are using Oracle, not MySQL as you tagged.
Problems with your query:
the correlation clause in the suqbuery is wrong: Table2.ID = Table2.ID succeds for all rows in table2, and hence returns more than one row, hence the error that you are getting
you need to handle the case when the subquery returns no rows, otherwise the null value propagates to your update: coalesce() can be used for this
Consider:
update table1
set count = count - coalesce(
(select t2.count from table2 t2 where t2.id = table1.id),
0
);
Or, alternatively:
update table1
set count = (select t2.count from table2 t2 where t2.id = table1.id)
where exists (select 1 from table2 t2 where t2.id = table1.id)
You can use LEFT JOIN including COALESCE function in order to update non-matching records along with preventing to have null values :
UPDATE Table1 t1
LEFT JOIN Table2 t2 ON t1.Id = t2.Id
SET t1.Count = Coalesce(t1.Count,0) - Coalesce(t2.Count,0)
Demo for MySQL Case
Update : seems that question is retagged Oracle. Then you can use such a MERGE Statement :
MERGE INTO Table1 t1
USING Table2 t2
ON (t1.Id = t2.Id)
WHEN MATCHED THEN
UPDATE SET t1.Count = Coalesce(t1.Count,0) - Coalesce(t2.Count,0)
Demo for Oracle Case
Coalesce() might be replaced with Nvl() for Oracle DB.
Related
I am writing an IF/Case statement that requires me to identify all the Ids from and ID column in Table1 that don't appear in a 2nd table Table2 which is left joined on to Table1 on the ID Column, And based on that IF statement I would like to produce a binary column called Missing with 1s, 0s.
Table1
ID
Region
a
US
b
US
c
Mexico
d
Japan
Table2
ID
Years
a
5
d
10
After joining this is what I have:
ID
Region
Years
a
US
5
b
US
null
c
Mexico
null
d
Japan
10
The final outcome should be:
ID
Region
Years
Missing
a
US
5
0
b
US
null
1
c
Mexico
null
1
d
Japan
10
0
I don't know how to Identify those specific Ids in the IF or CASE statement but the rest of the query I can write. I tried to write
IF(Table1.ID NOT IN Table2.ID, 1, 0) As Missing
but that did not work (some sort of unnest issue)
You may try:
SELECT t1.*, t2.ID IS NULL AS Missing
FROM Table1 t1
LEFT JOIN Table2 t2
ON t2.ID = t1.ID;
Using the IF() function we can try:
SELECT t1.*, IF(t2.ID IS NULL, 1, 0) AS Missing
FROM Table1 t1
LEFT JOIN Table2 t2
ON t2.ID = t1.ID;
Can anyone help with the following ?
I have 2 tables and I need to update table#1 with data from table#2 like the example below
Table 1 :
ID - Name - Engine ID
1 - x - NULL
Table 2 :
ID - Name
0 - x
Result (in Table 1) :
ID - Name - Engine ID
1 - x - 0
using loop over table 1
Although you haven't tagged your database product, the syntax is almost same for many SQL backends:
update table1
set engineId = t2.Id
from table1 t1
inner join table2 t2 on t1.Name = t2.Name;
Here is DBFiddle Demo for SQL Server
EDIT: In case you are using MySQL its syntax is slightly peculiar:
update Table1 t1
inner join Table2 t2 on t1.Name = t2.Name
set t1.engineId = t2.Id;
In most databases, you could do this with a correlated subquery:
update t1
set engine_id = (select engine_id from t2 where t2.name = t1.name)
where engine_id is null
Note that for this to properly work, there should be no duplicate name in t2 (otherwise, the subquery would possibly return multiple rows, which would cause the query to error).
I have 2 tables as follows:
Table 1:
ID FName
1 Basics
2 Machine1
3 master
4 Machine2
15 Machine3
16 Machine16
Table 2:
ParentID Name InitialValue
1 Active 1
2 MachineName Entrylevel
2 Active 1
3 Active 1
4 MachineName Midlevellevel
4 Active 1
15 MachineName Endlevel
15 Active 1
16 MachineName Miscellenious
16 Active 0
Here, ID of Table 1 is referred as Parent ID at Table 2. I want "Initial Value" of Table 2 for MachineName Rows (of Table 2) provided "InitialValue" of Table 2 for Active Rows (of Table 2) are 1
Result should be like
ID InitialValue
2 Entrylevel
4 Midlevellevel
15 Endlevel
You could join the second table twice, once for MachineName, and once for Active:
SELECT t.ID, machine.InitialValue
FROM table1 t
INNER JOIN table2 machine
ON t.ID = machine.ParentId
AND machine.Name = 'MachineName'
INNER JOIN table2 active
ON t.ID = active.ParentId
AND active.Name = 'Active'
AND active.InitialValue = 1;
About Joins
The JOIN syntax allows you to link records to the previous table in your FROM list, most of the time via a relationship of foreign key - primary key. In a distant past, we used to do that with a WHERE condition, but that really is outdated syntax.
In the above query, that relationship of primary key - foreign key is expressed with t.ID = machine.ParentId in the first case. Note the alias that was defined for table2, so we can refer to it with machine.
Some extra condition(s) are added to the join condition, such as machine.Name = 'MachineName'. Those could just as well have been placed in a WHERE clause, but I like it this way.
Then the same table is joined again, this time with another alias. This time it filters the "Active" 1 records. Note that if the ID in table1 does not have a matching record with those conditions, that parent record will be excluded from the results.
So now we have the table1 records with a matching "MachineName" record and are sure there is an "Active" 1 record for it as well. This is what needs to be output.
Not sure if this is standard SQL but it should work using MySQL.
select T1.ID, T2.InitialValue
from Table1 T1 inner join Table2 T2 on T1.ID = T2.ParentId
where
T2.Name <> 'Active'
and exists (
select * from Table2 T3 where T3.ParentId = T1.ID and T3.Name = 'Active' and T3.InitialValue = 1
)
SELECT t1.ID, t2.InitialValue
FROM table1 t1 join table2 t2 on t1.ID=t2.ParentID
WHERE t2.name LIKE 'MachineName'AND t1.ID= ANY(SELECT t22.ParentID
FROM table2 t22
WHERE t22.InitialValue=1)
I think this should work
//slightly changed the condition in WHERE clausule (t2.parentID changed to t1.ID)
I have a table with an id column (unique, primary), a name (not unique--in fact, most likely repeated), and a flag column which has values 0, 1, or 2. Let's say I reorder the table using the command
SELECT id, name, flag ORDER BY name, id
I want to produce using SQL a list of names where, when the rows in the reordering are read downward, there are two adjacent rows with the same name and flags of value 0 and 1 (in that order). Additionally, in that list, I want to have the ids of the two rows where this happened. If it happened more than once, there should be multiple rows.
So, for instance, in the following
id name flag
4 Bob 0
5 Bob 2
6 Bob 1
1 Cathy 0
7 Cathy 1
3 David 0
2 Elvis 2
8 Elvis 0
9 Elvis 1
I would want to select
name id1 id2
Cathy 1 7
Elvis 8 9
How do I do this?
I'm using MySQL.
EDIT: Note that the IDs for those adjacent rows might not be consecutive; they're only consecutive if we order by name. See, for example, Cathy.
Thanks!
try
select t1.name, t1.id as id1,t2.id as id2
from tablename t1, tablename t2
where t1.flag = 0 and t2.id = t1.id+1 and t2.flag = 1 and t1.name = t2.name
Try:
select t1.name, t1.id as id1,t2.id as id2
from tablename t1
join tablename t2
on t2.name = t1.name and t2.flag = t1.flag + 1 and t2.id =
(select min(t3.id) from tablename t3
where t1.name = t3.name and t1.id < t3.id)
EDIT: amended join to t2 to include lookup on subquery
Table1
...
LogEntryID *PrimaryKey*
Value
ThresholdID - - - Link to the appropriate threshold being applied to this log entry.
...
Table2
...
ThresholdID *PrimaryKey*
Threshold
...
All fields are integers.
The "..." thingies are there to show that these tables hold a lot more imformation than just this. They are set up this way for a reason, and I can't change it at this point.
I need write a SQL statement to select every record from Table1 where the Value field in that particular log record is less than the Threshold field in the linked record of Table2.
I'm newish to SQL, so I know this is a basic question.
If anyone can show me how this SQL statement would be structured, it would be greatly appreciated.
SELECT T1.*
FROM Table1 T1
JOIN Table2 T2 ON T2.ThresholdID = T1.ThresholdID
WHERE T2.Threshold > T1.Value
SELECT t1.*
FROM dbo.Table1 t1 INNER JOIN dbo.Table2 t2 ON t1.ThresholdID = t2.ThresholdID
WHERE t2.Threshold > t1.Value
SELECT * from table1 t1 join table2 t2 on (t1.thresholdId = t2.thresholdId)
where t1.value < t2.threshold;
SELECT t1.LogEntryID, t1.Value, t1.ThresholdID
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.ThresholdID = t2.ThresholdID
WHERE t1.Value < t2.threshold
SELECT * FROM Table1
JOIN Table2
ON table1.ThresholdID = table2.ThresholdID --(assuming table 2 holds the same value to link them together)
WHERE
value < thresholdvalue
A 'JOIN' connects 2 tables based on the 'ON' clause (which can be multipart, using 'AND' and 'OR')
If you have 3 entries in table 2 which share table1's primary key (a one-to-many association) you will receive 3 rows in your result set.
for the tables below, for example:
Table 1:
Key Value
1 Hi
2 Bye
Table 2:
Table1Key 2nd_word
1 You
1 fellow
1 friend
2 now
this query:
SELECT * FROM Table1
JOIN Table2
on table1.key = table2.table1key
gets this result set:
Key Value Table1Key 2nd_word
1 Hi 1 You
1 Hi 1 fellow
1 Hi 1 friend
2 Bye 2 now
Note that JOIN will only return results when there is a match in the 2nd table, it will not return a result if there is no match. You can LEFT JOIN for that (all fields from the second table will be NULL).
JOINs can also be strung together, the result from the previous JOIN is used in place of the original table.