Update specific column with the value of single column from another table - sql

I want to update the specific column with value of a single column from another table using sql query.
The specific column I want to update is in the WorkingTime table. Like for example I want to update its value by 1 depending on its IDNo and Date from TABLE 2
WorkingTime table:
IDNo | PeriodDate | SPLP | NVLP | NBLP | PLP | BLP | MLP | SLP | VLP | NSLP |
18-031 |06/11/2017 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
18-032 |06/12/2017 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
18-033 |06/13/2017 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
And the name of the column I want to update in WorkingTime is in the LeaveDetails. The column with the name LeaveType.
LeaveDetails:
Contro | IDNo | LeaveType| DateFrom | DateTo | NoOfDays |
000041 |18-031 | SPLP |06/11/2019|06/11/2019| 1 |
000042 |18-032 | NVLP |06/12/2019|06/12/2019| 1 |
000043 |18-033 | PLP |06/13/2019|06/13/2019| 1 |
And my expected result after the query is this
Expected result:
IDNo | PeriodDate | SPLP | NVLP | NBLP | PLP | BLP | MLP | SLP | VLP | NSLP |
18-031 |06/11/2017 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
18-032 |06/12/2017 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
18-018 |06/13/2017 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
Can anyone please help me with the query i will use to make this happen. Thank you in advance.

I'm unclear which tables/columns you are trying to update but you can update a column value in one table using the column value of a different table by using a sub query, for example:
UPDATE TABLE_1
SET LEAVETYPE =
(SELECT NEW_COLUMN FROM TABLE_2 WHERE PRIMARY_KEY = 'Something')
WHERE PRIMARY_KEY = 'Something'
;

Try to Use temp table. first take your data in temp table then update main table by using temp table data.
Or using join the table
update u
set u.assid = s.assid
from ud u
inner join sale s on
u.id = s.udid

One method is a series of case expressions and subqueries:
update table1
set splp = (case when exists (select 1
from table2 t2
where t2.idno = table1.idno and
t2.perioddate = t1.perioddate and
t2.leavetype = 'SPLP'
)
then 1 else table1.splp
end),
splp = (case when exists (select 1
from table2 t2
where t2.idno = table1.idno and
t2.perioddate = t1.perioddate and
t2.leavetype = 'NVLP'
)
then 1 else table1.nvlp
end),
. . .;
Depending on the database, there are other approach as well, but the above should work in any database.

Related

Oracle - Select row where desired column contains only one specific type of data

I've two Table
Table 1
+--------+--------+
| LC | STATUS |
+--------+--------+
| 010051 | 6 |
+--------+--------+
| 010071 | 2 |
+--------+--------+
| 010048 | 2 |
+--------+--------+
| 010113 | 2 |
+--------+--------+
| 010125 | 2 |
+--------+--------+
Table 2
+--------+-------------+-----------+------------+--------+
| LC | BILL | LAST_BILL | PAYMENT_BY | STATUS |
+--------+-------------+-----------+------------+--------+
| 010125 | BILL/17/001 | 0 | C | 6 |
+--------+-------------+-----------+------------+--------+
| 010125 | BILL/17/002 | 0 | I | 1 |
+--------+-------------+-----------+------------+--------+
| 010125 | BILL/17/003 | 0 | F | 1 |
+--------+-------------+-----------+------------+--------+
| 010125 | BILL/17/004 | 0 | C | 6 |
+--------+-------------+-----------+------------+--------+
| 010113 | BILL/17/005 | 0 | C | 6 |
+--------+-------------+-----------+------------+--------+
| 010113 | BILL/17/006 | 0 | I | 1 |
+--------+-------------+-----------+------------+--------+
| 010048 | BILL/17/007 | 0 | C | 6 |
+--------+-------------+-----------+------------+--------+
| 010071 | BILL/17/008 | 0 | C | 6 |
+--------+-------------+-----------+------------+--------+
Where I just want to get the LC whose PAYMENT_BY is 'C', but others who have 'C' value and other than 'C' value, I don't want to get this LC.
I've try following query, but I think there's have expert who can done it in better way or most tuning way.
SELECT LC
FROM (SELECT T1.LC
FROM TABLE1 T1, TABLE2 T2
WHERE T1.STATUS = 2
AND T1.LC = T2.LC
AND T2.PAYMENT_BY = 'C'
AND LAST_BILL = 0
AND T2.STATUS = 6
MINUS
SELECT T1.LC
FROM TABLE1 T1, TABLE2 T2
WHERE T1.STATUS = 2
AND T1.LC = T2.LC
AND T2.PAYMENT_BY = 'I'
AND LAST_BILL = 0)
Query/Expected Result:
+--------+
| LC |
+--------+
| 010048 |
+--------+
| 010071 |
+--------+
You can do it with NOT EXISTS:
select t2.lc from table2 t2
where
t2.payment_by = 'C'
and
not exists (
select lc from table2
where lc = t2.lc and payment_by <> 'C'
)
If you want all the columns of table2, then:
select t2.* from table2 t2
..........................
select t.lc,
count(case when t.payment_by = 'C' THEN 1 else NULL end ) as count_c,
count(case when t.payment_by <> 'C' THEN 1 else NULL end ) as count_not_c
from table2 t
group by t.lc
having count(case when t.payment_by <> 'C' THEN 1 else NULL end ) < 1
demo
If I understand correctly, I think group by and having is the simplest query:
select t2.lc
from table2 t2
group by t2.lc
having min(t2.payment_by) = 'C' and max(t2.payment_by) = 'C';
This also has the advantage of returning each lc exactly once.

Check if data for update is same as before in SQL Server

I have a table Table1:
ID | RefID | Answer | Points |
----+-------+---------+--------+
1 | 1 | 1 | 5 |
2 | 1 | 2 | 0 |
3 | 1 | 3 | 3 |
4 | 2 | 1 | 4 |
I have a result set in temp table Temp1 with same structure and have update Table1 only if for refID answer and points have changed, otherwise there should be deletion for this record.
I tried:
update table1
set table1.answer = temp1.answer,
table1.points = temp1.points
from table1
join temp1 on table1.refid = temp1.refid
where table1.answer != temp1.answer or table1.points != temp1.points
Here is a fiddle http://sqlfiddle.com/#!18/60424/1/1
However this is not working and don't know how to add the delete condition.
Desired result should be if tables not the same ex. (second row answer 2 points3):
ID | RefID | Answer | Points |
----+-------+---------+--------+
1 | 1 | 1 | 5 |
2 | 1 | 2 | 3 |
3 | 1 | 3 | 3 |
4 | 2 | 1 | 4 |
if they are same all records with refID are deleted.
Explanation when temp1 has this data
ID | RefID | Answer | Points |
----+-------+---------+--------+
12 | 1 | 1 | 5 |
13 | 1 | 2 | 0 |
14 | 1 | 3 | 3 |
EDIT: adding another id column questionid solved the update by adding this also in join.
Table structure is now:
ID | RefID | Qid |Answer | Points |
----+-------+------+-------+--------+
1 | 1 | 10 | 1 | 5 |
2 | 1 | 11 | 2 | 0 |
3 | 1 | 12 | 3 | 3 |
4 | 2 | 11 | 1 | 4 |
SQL for update is: (fiddle http://sqlfiddle.com/#!18/00f87/1/1) :
update table1
set table1.answer = temp1.answer,
table1.points = temp1.points
from table1
join temp1 on table1.refid = temp1.refid and table1.qid = temp1.qid
where table1.answer != temp1.answer or table1.points != temp1.points;
SELECT ID, refid, answer, points
FROM table1
How can I make the deletion case, if data is same ?
You need to add one more condition in the join to exactly match the column.Try this one.
update table1
set table1.answer=temp1.answer,
table1.points=temp1.points
from
table1 join temp1 on table1.refid=temp1.refid and **table1.ID=temp1.ID**
where table1.answer!=temp1.answer or table1.points!=temp1.points
I would first do the delete, and only then the update.
The reason for this is that once you've deleted all the records where the three columns are the same, your update statement becomes simpler - you only need the join, and no where clause:
DELETE t1
FROM table1 AS t1
JOIN temp1 ON t1.refid = temp1.refid
AND t1.qid = temp1.qid
AND t1.answer=temp1.answer
AND t1.points=temp1.points
UPDATE t1
SET answer = temp1.answer,
points = temp1.points
FROM table1 AS t1
JOIN temp1 ON t1.refid=temp1.refid
AND t1.qid = temp1.qid
I think from what i understood that you need to use id instead of refid or both if id is unique

SQL UPDATE only Duplicates

I have a SQL Table like this:
+------+------------+---------+---------+--------+
| id | x | y | z | status |
+------+------------+---------+---------+--------+
| 1 | bla | ja | 1 | 0 |
| 2 | blaa | jaa | 2 | 0 |
| 3 | bla | ja | 1 | 0 |
| 4 | blaaa | jaaa | 3 | 0 |
| 5 | blaa | jaa | 2 | 0 |
+------+------------+---------+---------+--------+
I want to UPDATE only the status column of the duplicate rows and not the first one.
With that statement i update every duplicate also the first row of a duplicate row:
UPDATE table INNER JOIN
(SELECT x, y, z FROM table GROUP BY x,y,z HAVING COUNT(id) > 1)
dup
ON table.x = dup.x && table.y = dup.y && table.z = dup.z
SET status = '1'
But thats no right because the table has to look after the UPDATE Statement like this:
+------+------------+---------+---------+--------+
| id | x | y | z | status |
+------+------------+---------+---------+--------+
| 1 | bla | ja | 1 | 0 |
| 2 | blaa | jaa | 2 | 0 |
| 3 | bla | ja | 1 | 1 |
| 4 | blaaa | jaaa | 3 | 0 |
| 5 | blaa | jaa | 2 | 1 |
+------+------------+---------+---------+--------+
I hope you can help me.
Thanks a lot.
Just play with a select statment like the one below until you have a list of the duplicates then update as shown.
UPDATE table set status = '1'
WHERE ID in (select id from(Select ROW_NUMBER() OVER (Partition By x,y,z,status) as dup,id) where dup>1)
Didn't say RDBMS so this is for SQL Server
I believe this is what you want:
UPDATE table t INNER JOIN
(SELECT x, y, z, MIN(id) as minid
FROM table
GROUP BY x, y, z
HAVING COUNT(id) > 1 -- not strictly necessary, but why not?
) dup
ON t.x = dup.x AND t.y = dup.y AND t.z = dup.z AND
t.id > dup.minid
SET status = 1;
This calculates the minimum id for each group and then updates all the other rows.

SQL: query one column in same table

A football manager here. How do I:
Select all matches that have kicked-off but never had a goal.
Select all matches that kicked-off more than 1h ago but haven't yet had a goal or a corner-kick.
| Match | Event | EventTime |
|-------------------------------------------|
| 1 | Kick-off | 2014-12-15T16:00:00 |
| 1 | Throw-in | 2014-12-15T16:15:00 |
| 1 | Goal | 2014-12-15T16:20:00 |
| 1 | Corner-kick | 2014-12-15T16:30:00 |
| 1 | End | 2014-12-15T17:30:00 |
| 2 | Kick-off | 2014-12-10T16:00:00 |
| 2 | Goal | 2014-12-10T16:01:00 |
| 3 | Kick-off | 2014-12-05T08:00:00 |
| 3 | Corner-kick | 2014-12-05T08:10:00 |
I feel this should be simple, but I'm stuck somehow.
1:
SELECT DISTINCT Match
FROM dbo.YourTable A
WHERE [Event] = 'Kick-off'
AND NOT EXISTS( SELECT 1 FROM dbo.YourTable
WHERE Match = A.Match
AND [Event] = 'Goal')
2:
SELECT DISTINCT Match
FROM dbo.YourTable A
WHERE [Event] = 'Kick-off'
AND EventTime <= GETDATE(HOUR,-1,GETDATE())
AND NOT EXISTS( SELECT 1 FROM dbo.YourTable
WHERE Match = A.Match
AND [Event] IN ('Goal','Corner-kick'))
You would do this with aggregation and a having clause. For the first:
select match
from table t
group by match
having sum(case when event = 'Kick-off' then 1 else 0 end) > 0 and
sum(case when event = 'Goal' then 1 else 0 end) = 0;
For the second:
select match
from table t
group by match
having max(sum case when event = 'Kick-off' then eventtime end) <= getdate() - 1.0/24 and
sum(case when event in ('Goal', 'Corner-Kick') then 1 else 0 end) = 0;
Each condition in the having clause counts the number of rows that match the condition. > 0 means that at least one row matched. = 0 means no rows match.

sql select throught join table

Hy all,
I need a little help with writing a select...the problem is the following:
I have the following tables:
help
+----+-------+---------+
| id | title | content |
+----+-------+---------+
| 1 | a | acont |
| 2 | b | bcont |
+----+-------+---------+
helptag
+----+------+
| id | name |
+----+------+
| 1 | atag |
| 2 | btag |
+----+------+
helphelptag(join table)
+--------+-----------+
| helpid | helptagid |
+--------+-----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 2 |
+--------+-----------+
I need to select those helps, whish has the ids i give.
So for example if i give tag_id 2, than both help 1 and 2
but if i give tag_id 1 and 2, than only help 1.
I've tried leftjoin, with the ids IN[tag_ids], but it gives back both helps if i give 1 and 2.
This is an example of a "set-within-sets" query. I like to solve this using aggregation and having clause. For your first question:
select helpid
from helphelptag
group by helpid
having sum(case when helptagid = 2 then 1 else 0 end) > 0;
For the second, just add another condition:
having sum(case when helptagid = 2 then 1 else 0 end) > 0 and
sum(case when helptagid = 1 then 1 else 0 end) > 0;
Each condition counts the number of rows that match a given condition.